我找不到关于在现实生活中的项目ARC性能影响的客观的研究。 官方文档说
编译器有效地消除了许多多余的保留/释放呼叫和很多努力已投入加快一般Objective-C运行。 特别是,常见的“返回保留/自动释放对象”模式更快,实际上并不把对象放入自动释放池,当方法的调用者是ARC代码。
已中继/由Tech-的fanboys变形为“ARC是更快”。
我知道肯定是我的测量。 我们最近迁移我们的iOS项目,ARC和我做了一些性能测量前/后的我们的代码(产品代码,编译时的一些CPU密集区-Os
标志,当然)。
我观察了70%(是70%)业绩倒退。 使用仪器来跟踪保留/释放事件,我意识到,编译器引入了地方你就不会做保留/释放对很多(预ARC环境)。 基本上,任何临时变强。 也就是说,我认为,业绩回归的来源。
原代码,在迁移之前,就已经相当优化。 有几乎没有做过任何自动释放。 因此,有通过切换到ARC小的提升空间。
幸运的是, 仪器能够证明我是最昂贵的挽留释放了ARC介绍/我能解除他们使用__unsafe_unretained。 这稍微缓解了业绩倒退。
没有任何人有这个或任何其他信息技术来避免性能的损失? (除了停用ARC)
谢谢。
编辑:我不是说ARC是因为对性能的影响不好。 使用ARC的优势在很大程度上是比性能优越的回归(在我们的代码,回归没有任何明显的效果,所以我让他走)。 我认为ARC一个很好的技术。 我将永远不会回到MRC。 我问这个问题,在好奇心的更多。
我只是通过对题目的绝大多数博客有点不高兴(如在这里 和那里 )或多或少给出了ARC代码会比MRC代码(这是我认为之前,我把我的手更快的印象)。 我真的有一种感觉,这是不是有些微基准测试之外的情况。 在最好的情况,你可以希望与看齐MRC,不是越快。 我做了涉及对象的操作(如在一个文件计数字)其他一些简单的测试。 每次ARC较慢(想过没有那么糟糕,因为70%的PERF回归我最初谈)
\ {开始嘲讽}
事实上,上述的文档没有回答这个问题:
为圆弧慢?
这取决于你测量什么,但一般“没有。” ......
这显然应该被理解为
\ {开始模仿}
嗯...嗯...我们不能说这是慢,因为这是一个新酷TECHNO,我们希望你能采纳。 因此,我们回答“没有”用双引号只是为了避免集体诉讼。 别再问愚蠢的问题。
\ {端模仿}
\ {端讽刺}
Answer 1:
这里是我的ARC VS MRC性能测量 。 性能测试项目可在github上 ,所以你可以添加你自己的测试。 只是一定要在设备上运行它。 在模拟的结果是扭曲的,而且往往有利于MRC的。
总结:
ARC和MRC一般都是相同的速度 。 在一般的代码应该是ARC下更快,但密集的循环可以慢和显著等等。
在低级别的测试ARC具有超过MRC速度的角度来看,由于优化的边缘(自动释放返回,@autoreleasepool)。
有一些代码,其中ARC插入额外保留/释放,不会严格必要MRC下,只要该应用程序是单线程的。 这种代码可ARC下会比较慢,但它不仅使在紧密循环差,并依赖于问题的代码了很多。
例如,接收对象应该保留它即使在MRC,因为它可能在多线程应用程序中的方法在运行时被释放的方法。 你可以省略MRC代码的事实使得速度更快,但本质上unsafer(虽然你很少遇到这样一个问题,如果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
}
遗传算法我在测试项目中使用的是与由于此ARC慢大约40%。 这是一个不好的(极端),例如,因为那样你应该看到用C重写的关键代码段更高的性能改进的算法,由于大量的插入/删除对NSMutableArray中的NSNumber对象的操作,并正在创建。
这是彻头彻尾的过失解雇ARC完全是因为它可以在某些情况下会比较慢 。 如果发现这些情况是性能的关键则-fno-objc-arc
代码或在C重写
ARC不应被视为支持或反对,因为性能方面的考虑。 ARC是一个工具,让是一个程序员的工作轻松了许多 。 它是由你来决定你是否喜欢浪费时间试图找到泄漏对象和与悬摆指针崩溃这么多,你宁愿坚持MRC。
Answer 2:
我认为,如果你得到一个类似性能回归的唯一可能的解释是,你的手工管理的代码是“不安全的”,我的意思是有潜在的内存泄漏和保留少以某种方式不安全所生成的程序内存管理/释放调用。
我不认为ARC代码是如此慢于手动管理的一个,如果人工管理写得很好,安全...
当然,我觉得太那个写得很好手动托管代码可能会比ARC一个稍快,但代价是什么? 大量的工作做手工...... 在大多数情况下,它是更多的麻烦比它的价值!
此外,我认为,ARC应该用垃圾收集环境,而不是一个完美的书面MRC, 一个人的大脑将永远是比计划聪明相比较(或至少我希望如此...... :-))...
但是,如果你有一个良好的书面MRC代码库和你真的确定那是安全的快,为什么把它ARC下? 手动保持它的内存管理,使用-fno-objc-arc
标志...使用ARC是不是强制性的专门为这些类型的原因。
Answer 3:
在那里你可能得到一个显着的性能回归情况是你发送信息或调用C / C ++函数具有对象参数,并且其中的指令的数量是每这种功能相对较小。 编译器将插入(并以后不会再次优化掉)一个保留为每个参数/释放对。
考虑上下文中,编译器可认识到,某些保留/释放对是不必要的。 不过我注意到,即使一个函数被调用其定义为静态的内联和驻留在同一个翻译单元来电,编译器将无法优化掉保留不必要对/释放要求的参数。
Answer 4:
我怕讲出来的东西的话题,并且还根据的猜测...
我想大多数来自ARC的性能提升是通过内联保留/释放调用而不是eliding他们。
此外,据我经验丰富,ARC通常引入了额外的保留/释放呼叫。 因为ARC是非常严格和保守,所以大多不执行保留/释放省音。 和许多新插入的保留/释放调用语义必需的,但MRC下由程序员省略。 (例如,所有上述通过在函数参数和临时变量)
所以,
呼叫保留的计数/释放实际上增加了很多严格满足语义完整性。
他们中的一些会非常保守的优化被省略。
实际调用保留/释放将优化内联 - 通过成为从动态的Objective-C的方法调用静态的C函数调用 - 因此调用本身的成本会降低很多。
其结果是,我们通常性能下降。 我意识到,我省略了很多保留使用ARC前/释放调用。 但正如你指出的,无论我们得到的,它的语义完整 ,仍然可以手动 -使确定的-通过使用省略掉__unsafe_unretained
。
Answer 5:
当然,临时变量都很强缺省情况下。 这是明确的和明确的记录。 而且,如果你仔细想清楚了,这是什么人通常希望。
MyWidget *widget=[[MyWidget alloc]init]; // 1
[myWidget mill]; // 2
如果小部件不强,新进myWidget将在第1行中创建和2号线,然后才能被释放,归零!
现在,这是千真万确的,如果你使用大量的临时变量 - 例如,如果你严格遵守迪米特法则 - 在紧密循环的中间,如果你是假定这些临时变量都没有表现性价比可言,因为世界上有大量的寄存器,然后你会感到惊讶。
这可能是你现在正在居住的角落。
但是,这是一个充满异国情调和特殊的地方! 大部分代码是不是在紧密循环的中间。 最密集的循环不会影响性能的瓶颈。 而最紧密的循环并不需要太多的中间变量。
相反,ARC能做到的方式,你不能做手工(虽然也许优化器)自动释放优化。 所以,如果有一个在你紧张的循环返回一个自动释放变量的函数,你可能与ARC更好。
过早的优化是一个坏主意。 你可能会在一个无法回避的性能角落,但大多数人都没有。 我花了我大部分时间在OS X中,可以肯定的,但它已经有好几年我有一个性能问题,即答案不是一种更好的算法。
(最后,如果ARC是造成70%的性能损失到你的应用,那么你正在做一个可怕的很多内存管理的关键路径上试想一下:你花70%的时间分配和释放的对象。这听起来像一个的经典案例像一个飞锤或对象缓存或回收池!)
文章来源: Are there any concrete study of the performance impact of using ARC?