Reactivecocoa: 原子:SPINLOCK在iOS中不安全

创建于 2015-12-15  ·  20评论  ·  资料来源: ReactiveCocoa/ReactiveCocoa

https://twitter.com/steipete/status/676851647042203648

我将不发表任何评论(我只是说...如果在iOS上是非法的,为什么它是公共API?)

显然pthread互斥体现在更快了。 我们应该创建一个基准进行比较,然后尝试将Atomic转换为此(以及RACCompoundDisposableRACSerialDisposable吗?)

help wanted

最有用的评论

我今天发现了这个线程,并对不同类型的同步进行了调查,并在iOS模拟器和真实设备上执行了基准测试。
结果对我来说非常有趣。 在iOS 10中,dispatch_semaphore的性能明显下降,这可能是出于线程优先级方面的改变。
这是iOS中可用的基本同步机制的摘要图。 所有测试均使用发布配置运行(快速优化-O)

2016-06-29 17 58 39

SDK9的基准代码
SDK10的基准代码

所有20条评论

我什至不知道“非法”是什么意思。

nope

我只是很好奇,因为我从一开始就不在身边,但是为什么Atomic类型首先使用OSSpinLock Atomic类型呢?

是否使用了NSLock ,然后显示它太慢,然后对pthread_mutex_t进行了测试,发现它也太慢了? 不幸的是,git在“移动源……”之前没有历史记录

我不希望在非内核,非设备驱动程序的上下文中使用自旋锁,这就是我问的原因。 如果有的话,我会说这里的错误是根本使用了OSSpinLock 。 :stuck_out_tongue:

为了在我上面的评论中添加一个对策,这并没有标题那么大的麻烦: https :

即使在CPU不足的情况下,关键部分也是如此之小,在实际情况下可能还可以。
@Twitter上的

至于@kastiglione的上述评论:

我什至不知道“非法”是什么意思。

我没有答案,但是我猜想ARM CPU中的某些东西不允许自旋锁原语享受与Intel CPU一样的许多好处/保证/假设。 (但根据https://twitter.com/Catfish_Man/status/676851988596809728可能不是全部)

无论如何,在实践中可能“什么也看不到”,而是应该进行一些研究以替换为更安全的原语,并测量任何性能下降,如

我确实认为我们应该替换对OSSpinLock ,但是鉴于给我们提供的文档,我认为使用它们的理由是有效的。

是的,并且感谢您提供的相关历史记录。 不知道为什么当请求给定文件的历史记录时GitHub不执行git log --follow

无论如何,我将重申“可能很好”。 使用“现在更快”的互斥锁可能是一项简单的任务,但是在不知道如何配置/测试它们的情况下却并非如此。 那里有任何建议/指针吗?

至于如果/当性能成为问题时的前进之路,无锁队列值得研究。 (对于不熟悉该概念的读者,这是一篇不错的文章:http://www.linuxjournal.com/content/lock-free-multi-producer-multi-consumer-queue-ring-buffer?page = 0,0)。 不久前,我为内部音频库构建了类似的东西,也许我可以像这样将其改编为一般用途。

使用“现在更快”的互斥锁可能是一项简单的任务,但是在不知道如何配置/测试它们的情况下却并非如此。 那里有任何建议/指针吗?

我在Instruments的Time Profiler和Allocations中运行GitHub Desktop,并专注于RAC繁重的堆栈。 您现在必须与@joshaber@mdiep交谈。 :眨眼:

好的,很高兴知道。 我想象Swift端的东西将需要类似的大/深代码库来进行测试。 我已经长大了一些我自己在过去的几个月中1,但我不知道我是否推RAC“够硬”,以获得足够的样品出来。 诸如我的应用程序会在其他工具图表中冒出很多其他东西。 :微笑:

1个插头! http://capoapp.com ,其中http://capoapp.com/neptune是最新的,完全设计的using-RAC4组件。

我今天写了一篇博客文章,详细介绍了为什么自旋锁在iOS上“非法”: http :

我不久前中断了Atomic,并将其迁移到pthread_mutex_lock。 众所周知,这是最好的锁–没有像NSLock这样的动态调度,没有像spinlock这样的即时锁,不会像spin lock那样浪费能量。

随意从我的仓库中复制粘贴源代码,或使用它做任何你想做的事情。

https://github.com/Adlai-Holler/Atomic
https://github.com/Adlai-Holler/Atomic/blob/master/Atomic/Atomic.swift

@kballard ,这是一个很好的解释,谢谢!

我对此不是很坚决,因为我不是这方面的专家。 尽管我很乐意自己进行更改,但我会决定更改(或不更改)我们使用哪种类型的锁,因此请他人参考!

没有源代码,这样的基准完全没有用。 而且,您只为每个结构显示一个时间,而没有记录该时间实际代表的时间。 各种构造的行为会有所不同,具体取决于它们是否处于争用状态,争用锁的线程的优先级等。 @synchronized也是一个奇怪的野兽,其性能将在很大程度上取决于访问模式,例如,同时要输入/退出多少个@synchronized块,是重复锁定同一对象还是锁定新对象,等等。

注意: dispatch_semaphore不捐赠优先级,这是另一个潜在的陷阱。

@jspahrsummers @kballard我有一个使用原子CAS的实现。 如果有任何兴趣,我很乐意提交PR。

编辑:查看Atomic的使用,我认为我的实现不会有用。 如果您可以进行幂等更新,则CAS可以使您在内存中进行某种乐观的事务,这可能很棒,但是需要进行大量重构(尽管如果所有内容都是CoW不可变的,那么它确实工作得很好,那么您确实可以将突变视为内存中的交易)。

我今天发现了这个线程,并对不同类型的同步进行了调查,并在iOS模拟器和真实设备上执行了基准测试。
结果对我来说非常有趣。 在iOS 10中,dispatch_semaphore的性能明显下降,这可能是出于线程优先级方面的改变。
这是iOS中可用的基本同步机制的摘要图。 所有测试均使用发布配置运行(快速优化-O)

2016-06-29 17 58 39

SDK9的基准代码
SDK10的基准代码

您的电话号码对我来说似乎很可疑。 您运行了多少次测试?

为了进行比较,我在OS X 10.11.5上运行了自己的基准测试(源代码),使用了我不久前写的hacky基准测试工具。 我运行了整个基准测试10次,从每个测试中删除了底部和顶部2个数字(以消除异常值),其余数字产生了以下范围:

无同步:22-41ns
自旋锁:24ns
信号量:29ns
NSLock:45-71ns
互斥体:40-64ns
同步:75-122ns
队列:505-554ns

从中可以看出,自旋锁是最便宜的,其次是信号量,然后是互斥锁,然后是NSLock,紧随互斥锁之后(因为它基本上是互斥锁+ objc_msgSend),然后同步的开销几乎是后者的两倍,最后队列最终变得极其昂贵昂贵,比我预期的要贵得多。

如您所见, @ kballard ,我的基准测试非常简单,但是它使用默认的xctest机制来衡量执行时间。 数字是每个测试的平均运行时间,而不是每个同步的平均运行时间。 通常,您和我的结果是相关的,除了队列,我们​​以前认为还不错

原因

此页面是否有帮助?
0 / 5 - 0 等级