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 工具,可以诊断问题。
五、参考
GCD 使用若干注意事项的更多相关文章
- WPF:自动执行"机器人"程序若干注意事项
企业应用中,经常会遇到一些需要定时自动执行的程序来完成某些功能,比如:自动定时从第三方web service取回数据.定时对历史数据进行清理.定时向ftp上传业务数据... 这类程序,我习惯称为“机器 ...
- 解决Bootstrap 附加导航(Affix)的问题和使用时若干注意事项
1.要清楚Affix分别赋予的class, 开始:affix-top 达到top参数:affix 达到bottom参数:affix-bottom 2.一定要自定义这些class,否则 插件会默认给你在 ...
- 制作C/C++动态链接库(dll)若干注意事项
一.C\C++ 运行时库编译选项简单说明 问题:我的dll别人没法用 运行时库是个很复杂的东西,作为开发过程中dll制作需要了解的一部分,这里主要简单介绍一下如何选择编译选项. 在我们的开发过程中时常 ...
- Oracle EBS Form 发布到Server端的注意事项
前段时间在本地XP系统上测试了一些整合javabean的Form例子,想着发布到服务器段去看看能否运行正常,一开始以为会和本地XP系统一样,部署到相关的目录下进行一些配置就可以了,但实际过程却和想象的 ...
- iOS面试题大全-点亮你iOS技能树
所有的内容大部分来自于网络的搜集,所以我不是一个创造者,而是一个搬运工.我尽量把题目,尤其是参考答案的出处列明.若有任何疑问,建议,意见,请联系我. 第一部分面试题来源于iOS-Developer-I ...
- iOS面试题
一个区分度很大的面试题 考察一个面试者基础咋样,基本上问一个 @property 就够了: @property 后面可以有哪些修饰符? 线程安全的: atomic,nonatomic 访问权限的 re ...
- python之路四
内建函数 内建函数详解: 1. abs(x) abs()函数返回数字(可为普通型.长整型或浮点型)的绝对值.如果给出复数,返回值就是该复数的模.例如: >>>print abs(-2 ...
- 李洪强iOS经典面试题下
李洪强iOS经典面试题下 21. 下面的代码输出什么? @implementation Son : Father - (id)init { self = [super init]; if (self) ...
- 招聘一个靠谱的 iOS
近一年内陆续面试了不少人了,从面试者到面试官的转变让我对 iOS 招聘有了更多的感受.经过了前段时间的一大波面试,我们终于找到了志同道合的小伙伴,面试也暂时告一段落了.总结下面试人过程中的感受,你也可 ...
随机推荐
- ArcGIS GP服务的发布及调用
参考https://www.jianshu.com/p/5331fa708fe5
- jqzoom插件图片放大功能的一些BUG
建议使用cloud-zoom插件,jqzoom插件就不要使用了 点击查看——图片放大镜——jQuery插件Cloud Zoom 刚开始使用的是jqzoom插件,但问题太多了,就不说插入到页面中使用了, ...
- Mac 安装Django
首先 我电脑上的python 是 安装Django 是需要通过 pip 来安装的 最新办的python3.4 应该内置了pip 因此这里 需要下载安装pip pip是常用的Python包管理 ...
- Golang之实现(链表)
链表算法 package main import "fmt" type LinkNode struct { data interface{} next *LinkNode } ty ...
- Solr分词搜索结果不准确
Solr的schema.xml默认配置分词后条件取 OR 例如:大众1.6T 系统会自动分词为 [大众] [1.6T](ps:不同分词器分词效果不同) 会搜索出包含 [大众 OR 1.6T] ...
- 给tabhost加上点击监听,不是onTabChanged(String)监听
给tabhost加上点击监听,不是onTabChanged(String)监听 2012-08-11 01:43 5209人阅读 评论(0) 收藏 举报 stringandroidlayoutnull ...
- HITS
HITS 1 概述 HITS(hypertext induced topic search)超链接归纳主题搜索是由kleinbers在90年代提出的基于链接分析的网页排名算法.Hits算法是利用Hub ...
- [解决]--java_out: User.proto: User.proto: Cannot generate Java output because the file 's
在使用 protocol buffer 的时候,用.proto文件生成代码文件时报错 使用命令 protoc.exe --java_out c:\logs\ User.proto User.proto ...
- UVALive - 6434 —(思维题)
题意:给出了你由n个数组成的序列,让你将这个序列分为成m个集合,使得每一个集合的最大值减最小值的差相加最小.(如果某集合只有一个数字,则最大值减最小值为0) . 思路:首先我们不难想到,最优的分配方法 ...
- TOAD连接ORACLE而不装ORACLE 客户端的方法
TOAD连接ORACLE而不装ORACLE 客户端的方法 原来连接ORACLE总是要装ORACLE客户端,挺麻烦得,一方面要带ORACLE得盘,另一方面,装这么大得东西也让人很不爽. ORACLE好像 ...