MRC彷佛已是一个上古时代的话题了,不过我仍是绕有兴致的把它翻出来。由于,今天我被一个问题问住了:ARC与MRC的性能方面孰优劣。确实,以前没有对比过。html
先来作个测试吧。首先咱们须要一个计时辅助函数,我选择使用mach_absolute_time,计算时间差的函数以下:ios
double subtractTimes(uint64_t endTime, uint64_t startTime) { uint64_t difference = endTime - startTime; static double conversion = 0.0; if(conversion == 0.0) { mach_timebase_info_data_t info; kern_return_t err = mach_timebase_info(&info); //Convert the timebaseinto seconds if(err == 0) conversion = 1e-9 * (double) info.numer / (double) info.denom; } return conversion * (double)difference; }
而后定义两个测试类,一个是ARC环境下的,一个是MRC环境下的,分别以下:多线程
// Test1.m + (void)test { uint64_t start,stop; start = mach_absolute_time(); for (int i = 0; i < 1000000; i++) { NSArray *array = [[NSArray alloc] init]; } stop = mach_absolute_time(); double diff = subtractTimes(stop, start); NSLog(@"ARC total time in seconds = %f\n", diff); } // Test2.m // 在target->Build Phases->Compile Sources中,添加编译标识-fno-objc-arc + (void)test { uint64_t start,stop; start = mach_absolute_time(); for (int i = 0; i < 1000000; i++) { NSArray *array = [[NSArray alloc] init]; [array release]; } stop = mach_absolute_time(); double diff = subtractTimes(stop, start); NSLog(@"MRC total time in seconds = %f\n", diff); }
多运行几组测试,而后挑两组吧来看看,数据以下:app
// A组 ARC total time in seconds = 0.077761 MRC total time in seconds = 0.072469 // B组 ARC total time in seconds = 0.075722 MRC total time in seconds = 0.101671
从上面的数据能够看到,ARC与MRC各有快慢的状况。即便上升到统计学的角度,ARC也只是以轻微的优点胜出。看来个人测试姿式不对,并无证实哪一方占绝对的优点。ide
嗯,那咱们再来看看官方文档是怎么说的吧。在Transitioning to ARC Release Notes中有这么一段话:函数
Is ARC slow?性能
It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneousretain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.测试
One issue to be aware of is that the optimizer is not run in common debug configurations, so expect to see a lot more retain/release traffic at -O0 than at -Os.优化
再来看看别人的数据吧。Steffen Itterheim在Confirmed: Objective-C ARC is slow. Don’t use it! (sarcasm off)一文中给出了大量的测试数据。这篇文章是2013.3.20号发表的。Steffen Itterheim经过他的测试得出一个结论ui
ARC is generally faster, and ARC can indeed be slower
嗯,有些矛盾。不过在文章中,Steffen Itterheim指出大部分状况下,ARC的性能是更好的,这主要得益于一些底层的优化以及autorelease pool的优化,这个从官方文档也能看到。但在一些状况下,ARC确实是更慢,ARC会发送一些额外的retain/release消息,如一些涉及到临时变量的地方,看下面这段代码:
// this is typical MRC code: { id object = [array objectAtIndex:0]; [object doSomething]; [object doAnotherThing]; } // this is what ARC does (and what is considered best practice under MRC): { id object = [array objectAtIndex:0]; [object retain]; // inserted by ARC [object doSomething]; [object doAnotherThing]; [object release]; // inserted by ARC }
另外,在带对象参数的方法中,也有相似的操做:
// this is typical MRC code: -(void) someMethod:(id)object { [object doSomething]; [object doAnotherThing]; } // this is what ARC does (and what is considered best practice under MRC): -(void) someMethod:(id)object { [object retain]; // inserted by ARC [object doSomething]; [object doAnotherThing]; [object release]; // inserted by ARC }
这些些额外的retain/release操做也成了下降ARC环境下程序性能的罪魁祸首。但实际上,之因此添加这些额外的retain/release操做,是为了保证代码运行的正确性。若是只是在单线程中执行这些操做,可能确实不必添加这些额外的操做。但一旦涉及以多线程的操做,问题就来了。如上面的方法中,object彻底有可能在doSoming和doAnotherThing方法调用之间被释放。为了不这种状况的发生,便在方法开始处添加了[object retain],而在方法结束后,添加了[object release]操做。
若是想了解更多关于ARC与MRC性能的讨论,能够阅读一下Are there any concrete study of the performance impact of using ARC?与ARC vs. MRC Performance,在此就不过多的摘抄了。
实际上,即使是ARC的性能不如MRC,咱们也应该去使用ARC,所以它给咱们带来的好处是不言而喻的。咱们再也不须要像使用MRC那样,去过多的关注内存问题(虽然内存是必须关注的),而将更多的时间放在咱们真正关心的事情上。若是真的对性能很是关切的话,能够考虑直接用C或C++。反正我是不会再回到MRC时代了。