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形式返回。
如何找到这种阻塞的任务
- 自定义队列必须添加名称
- 关注xcode堆栈信息
- 主线程阻塞很好排查,子线程阻塞还是第一次见。攒点经验了。
二、串行队列阻塞造成内存数据挤压
1. 共享屏幕内存超50MB问题沟通
问题:iOS 屏幕分享,需要开启一个Extension,但内存限制50MB,超过50MB分享直接闪退。
分析
- 这个问题本来一直是同事在跟踪,发现闪退之后,同事去搜索了很多,发现云信是使用socket方式先把数据发送到主进程,再由主进程推。而声网并没有处理这个问题。
- 声网那边跟了很久,暂时无果,同事这边做了临时处理,如果内存超过45MB时,不推流,但造成的现象就是经常出现分享视频流卡主不动。
- 仔细研究了声网分享出来的demo,声网使用- (void)processSampleBuffer:withType:在不停的推流,调用的是一个串行队列。于是大胆的分析了下,声网捕捉到屏幕变化,不断的抓取屏幕生成CMSampleBufferRef对象,塞到串行队列。而CMSampleBufferRef对象占用内存比较大,当屏幕变化比较大时,造成串行队列挤压。很快就超过50MB。
- 最后也得到声网的验证。与内存被打爆这个原因一样。