GCD 使用若干注意事项

这篇文章写的是看完 WWDC 17 - Modernizing GCD Usage 之后的笔记。

一、Parallelism & Concurrency

Parallelism 指的是在多个 CPU 核上同时跑代码。

DispatchQueue.concurrentPerform(iterations: 100) { (i) in
    print("\(i)")
}

为了更好的利用多个 CPU 的优势,把任务分为尽可能多的部分,方便调度。
如果只有 3 个部分,那么很可能会出现 Bubble,即有时间片没有被利用。

Concurrency 即我们通常说的多任务,这个 session 讲的也大部分是 Concurrency。

二、Context Switching

上下文切换是 Concurrency 可以实现的基础,但是过多的上下文切换会带来性能问题。

2.1 重复的获取互斥资源引发的等待

每次切换需要 10μs 的量级

可以考虑用 un_fair_lock 来解决。
先来看 fair_lock。多个线程同时竞争这个锁得时候, 会考虑公平性尽可能的让不同的线程公平。 这个公平其实是有很大的性能损失换来的。

在上面的图中,锁先被线程 1 持有,然后释放,被线程 2 持有,引起一次上下文切换。

而在非公平锁中,线程 1 释放锁之后,马上又获得了锁,没有造成上下文切换。

可以用 Instrument 发现问题,然后选择适当的锁。

2.2 重复地在不同的操作 (operations)中切换

一个例子是有很多网络连接,而每一个连接都对应一个串行队列。当网络发生变化时,这些队列中的代码都要被执行。
假如队列形式如下,S 表示网络发生变化, Q 表示网络变化时代码要执行的串行队列。

当网络变化时,会有 3 个队列生成,对应三个线程。

显然会发生上下文切换。

如果我们指定 3 个队列的 target 是同一个 queue,如下图:

那么在网络发生变化时,这三个队列的代码将在同一个 queue 中执行,不会有上下文切换。

此外,如果把太多的任务加到全局并行队列,也会导致生成太多线程。

• If workitems block, more threads will be created
• May lead to thread explosion

苹果推荐的方法是,每一个子系统(数据库、网络。。。)有一个队列层级,如下图:

三、统一队列标识符 (Unified Queue Identity)

具体原理没有看明白,大概是每一个队列都在内核中有一个标志符,可以根据这个标识符做优化。
在之前,把两个 source 的队列设置为一个,当处理 S1 时, S2 被触发,那么会新建一个线程。

经过优化之后,不会创建一个额外的线程了。
大致原理是当 S2 触发时,系统知道对应的队列正在执行,于是做了一个标记。
当处理完毕之后,再进行相应处理。

四、如何处理代码

4.1 在 activation 之后不要改变 dispatch object

即在 activate 函数调用之后,不要改变 source handler 和 target queue。因为系统会创建一个快照,根据这个快照来优化调度。

let mySource = DispatchSource.makeReadSource(fileDescriptor: fd, queue: myQueue)
mySource.setEventHandler(qos: .userInteractive) { … }
mySource.setCancelHandler { close(fd) }
mySource.activate()
mySource.setTarget(queue: otherQueue)//wrong!!!!!!!!!!!!!!!!

4.2 保护好队列的层级

使用新的函数,在创建队列时指定 target queue。

Q1 = dispatch_queue_create_with_target("Q1", DISPATCH_QUEUE_SERIAL, EQ)
//下面被淘汰啦  
Q1 = dispatch_queue_create("Q1",DISPATCH_QUEUE_SERIAL)
dispatch_set_target_queue(Q1, EQ)

4.3 使用新的工具

Instrument 带有 GCDPerformance 工具,可以诊断问题。

五、参考

转载于:https://www.cnblogs.com/huahuahu/p/GCD-shi-yong-ruo-gan-zhu-yi-shi-xiang.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值