Fré*_* DJ 12 performance objective-c automatic-ref-counting
我无法在现实生活中找到关于ARC性能影响的客观研究. 官方文件说
编译器有效地消除了许多无关的保留/释放调用,并且已经投入了大量精力来加速Objective-C运行时.特别是,当方法的调用者是ARC代码时,常见的"返回保留/自动释放对象"模式要快得多,并且实际上并不将对象放入自动释放池中.
由技术爱好者传播/变形为"ARC更快".
我所知道的就是我所测量的.我们最近将我们的iOS项目迁移到了ARC,我在代码的一些CPU密集区域之前/之后进行了一些性能测量(生产代码,-Os
当然是用标志编译的).
我观察到70%(是70%)的性能回归.使用Instruments跟踪保留/释放事件,我意识到编译器在你不会这样做的区域引入了很多保留/释放对(在ARC之前的环境中).基本上,任何临时变得强大.也就是说,我相信,性能回归的来源.
迁移之前的原始代码已经非常优化.几乎没有任何自动释放.因此,切换到ARC几乎没有改进的余地.
幸运的是,Instruments能够向我展示ARC引入的最昂贵的保留/释放,并且我能够使用__unsafe_unretained来停用它们.这略微减轻了性能回归.
是否有人有关于此技术或其他技术的任何信息以避免性能损失?(除了停用ARC)
谢谢.
编辑:我不是说ARC因为性能影响而坏.使用ARC的优势在很大程度上优于性能回归(在我们的代码中,回归没有任何明显的效果,所以我放手了).我认为ARC是一项非常好的技术.我永远不会回到MRC.我好奇地问这个问题.
我只是对这个主题的绝大多数博客(比如这里 和那里)略微恼火,或多或少给人的印象是ARC代码会比MRC代码更快(我之前我相信的事情是我把它放在它上面).而且我确实感觉在某些微观基准测试之外并非如此.充其量你可以希望与MRC相提并论,而不是更快.我做了一些其他涉及对象操作的简单测试(比如计算文档中的单词).每次ARC都比较慢(认为不像我最初谈论的70%的回归那样糟糕)
\ {开始嘲讽}
事实上,上述文档确实回答了这个问题:
ARC慢吗?
这取决于你测量的是什么,但通常是"不".
显然应该理解为
\ {开始模仿}
嗯......哼......我们不能说它慢一点,因为这是一个新的酷技术,我们希望你采用它.所以我们用双引号回答"否"只是为了避免集体诉讼.并停止问愚蠢的问题.
\ {端模仿}
\ {端讽刺}
以下是我的ARC vs MRC性能测量.性能测试项目在github上可用,因此您可以添加自己的测试.一定要在设备上运行它.模拟器中的结果是偏斜的,并且通常有利于MRC.
总结一下:
ARC和MRC的速度通常相同.一般来说,在ARC下代码应该更快,但是紧密循环可以更慢且显着.
在低级测试中,由于优化(自动释放返回,@ autoreleasepool),ARC在速度方面优于MRC.
有一些代码,ARC会在MRC下插入额外的保留/释放,只要应用程序是单线程的.在ARC下这样的代码可能会更慢,尽管它只会在紧密循环中产生影响,并且在很大程度上取决于所讨论的代码.
例如,接收对象的方法应该在MRC下保留它,因为它可能在方法运行时在多线程应用程序中释放.您可以在MRC中省略该代码的事实使其更快,但本质上没有更好的(尽管您很少会遇到这样的问题,如果你希望你没有这么做的话,OTOH).例:
-(void) someMethod:(id)object
{
[object retain]; // inserted by ARC, good practice under MRC
[object doSomething];
[object doAnotherThing];
[object release]; // inserted by ARC, good practice under MRC
}
Run Code Online (Sandbox Code Playgroud)
由于这个原因,我在测试项目中使用的遗传算法使ARC大约慢了40%.这是一个不好的(极端),例如,因为那样你应该看到用C重写的关键代码段更高的性能改进的算法,由于大量的插入/删除对NSMutableArray中的NSNumber对象的操作,并正在创建.
完全解雇ARC是完全疏忽的,因为在某些情况下它可能会更慢.如果您发现这些情况对性能至关重要,那么-fno-objc-arc
该代码或在C中重写它.
出于性能考虑,不应考虑使用ARC.ARC是一种使程序员的工作变得更容易的工具.由你决定是否要浪费时间试图找到泄漏的物体和悬挂指针崩溃,以至于你宁愿坚持使用MRC.
我认为,如果您得到类似的性能回归,唯一可能的解释是您的手动托管代码“不安全”,我的意思是存在潜在的内存泄漏和较少的保留/释放调用,这使得程序内存管理在某种程度上不安全。
我不认为 ARC 代码比手动管理的代码慢,如果手动管理的代码写得好并且安全的话......
当然,我也认为编写良好的手动管理代码可能比 ARC 代码稍快,但代价是什么?更多的工作需要手工完成... 在大多数情况下,这比它的价值更麻烦!
另外,我认为 ARC 应该与垃圾收集器环境进行比较,而不是与完美的书面 MRC 进行比较,人脑永远比程序更聪明(或者至少我希望如此......:-)) ......
但是,如果您有一个编写良好的 MRC 代码库,并且您确实确定它是安全且更快的,那么为什么将其放在 ARC 下呢?使用-fno-objc-arc
标志手动管理内存...使用 ARC 不是强制性的,特别是出于这些原因。