iOS 串行队列阻塞引起消息加载慢、分享内存堆积超50MB等问题

2021-02-06  本文已影响0人  某非著名程序员

一、串行队列阻塞

1. 进入聊天界面消息加载不出来(偶现)

问题

网络正常时,点击进入会话,偶现一直在加载。过了段时间又正常。

原因

进入聊天窗口拉取消息、加载历史消息,统一在串行队列中操作。
下面这段是出现问题的伪代码:

dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(0);
...
[BLClientKitDolpServer send:msgDto callback:^(DolpMessageResponse *object, NSError *error) {
     ...
        dispatch_semaphore_signal(semaphore_t);
    }];
    dispatch_semaphore_wait(semaphore_t, DISPATCH_TIME_FOREVER);
    }

弱网时,网络响应比较慢,当前串行队列的任务被阻塞。导致再次进入会话,串行的任务也不会立即执行。
超时结束,展示也就正常了。

解决方案

网络请求不需要异步转同步,把结果以block形式返回。

如何找到这种阻塞的任务

  1. 自定义队列必须添加名称
  2. 关注xcode堆栈信息
  3. 主线程阻塞很好排查,子线程阻塞还是第一次见。攒点经验了。
堆栈

二、串行队列阻塞造成内存数据挤压

1. 共享屏幕内存超50MB问题沟通

问题:iOS 屏幕分享,需要开启一个Extension,但内存限制50MB,超过50MB分享直接闪退。

分析

  1. 这个问题本来一直是同事在跟踪,发现闪退之后,同事去搜索了很多,发现云信是使用socket方式先把数据发送到主进程,再由主进程推。而声网并没有处理这个问题。
  2. 声网那边跟了很久,暂时无果,同事这边做了临时处理,如果内存超过45MB时,不推流,但造成的现象就是经常出现分享视频流卡主不动。
  3. 仔细研究了声网分享出来的demo,声网使用- (void)processSampleBuffer:withType:在不停的推流,调用的是一个串行队列。于是大胆的分析了下,声网捕捉到屏幕变化,不断的抓取屏幕生成CMSampleBufferRef对象,塞到串行队列。而CMSampleBufferRef对象占用内存比较大,当屏幕变化比较大时,造成串行队列挤压。很快就超过50MB。
  4. 最后也得到声网的验证。与内存被打爆这个原因一样。
上一篇 下一篇

猜你喜欢

热点阅读