ARC与MRC的性能对比

MRC似乎已经是一个上古时代的话题了,不过我还是绕有兴致的把它翻出来。因为,今天我被一个问题问住了:ARC与MRC的性能方面孰优劣。确实,之前没有对比过。

先来做个测试吧。首先我们需要一个计时辅助函数,我选择使用mach_absolute_time,计算时间差的函数如下:

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);
}

多运行几组测试,然后挑两组吧来看看,数据如下:

// 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也只是以轻微的优势胜出。看来我的测试姿势不对,并没有证明哪一方占绝对的优势。

嗯,那我们再来看看官方文档是怎么说的吧。在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通过他的测试得出一个结论

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时代了。

时间: 2024-10-23 01:40:36

ARC与MRC的性能对比的相关文章

iOS内存管理 ARC与MRC

想驾驭一门语言,首先要掌握它的内存管理特性.iOS开发经历了MRC到ARC的过程,下面就记录一下本人对iOS内存管理方面的一些理解. 说到iOS开发,肯定离不开objective-c语言(以下简称OC).OC的内存管理机制叫做引用计数,就是一块内存地址可以同时被多个对象引用,每引用一次,引用计数都会递增1,当对象每解除一次引用,引用计数就会递减1,直到引用计数为0时,系统才会讲这块内存地址回收释放掉,这与C/C++语言有些不同,但是它们都遵守同一个内存管理法则:谁申请,谁释放. 在早些时候,iO

ARM演化变迁性能对比

ARM演化变迁: ARM经典:ARM7,ARM9,ARM11性能依次提升. Cortex: M系列:Cortex-M0,Cortex-M1,Cortex-M2,Cortex-M3,Cortex-M4应用于工控领域(没有操作系统)类比单片机性能比单片机强. R系列:Cortex-R4面向实时应用,可以运行操作系统. A系列:Cortex-A5,Cortex-A8,Cortex-A9主要面向多媒体应用,现代智能手机基本采用Cortex-A系列.M,R,A系列性能也是依此提升. 其性能对比:ARM7与

自己写的轻量级PHP框架trig与laravel,yii性能对比

看了下当前最热门的php开发框架,想对比一下自己写的框架与这些框架的性能对比. 看结果对比. laravel 5.1: yii2: trig: 自己写的框架速度是lavavel 5.1的8倍,是yii2的5.3倍.

Struts2、SpringMVC、Servlet(Jsp)性能对比 测试

Struts2.SpringMVC.Servlet(Jsp)性能对比 测试 . Servlet的性能应该是最好的,可以做为参考基准,其它测试都要向它看齐,参照它. 做为一个程序员,对于各个框架的性能要有一个基本的认知,便于选型时做出正确的决策. 在测试中发现了什么也不要大喊大叫,因为这些都是Java程序员的基础知识. 人人都要了解. ----------------------------------------------------------------------------------

开发语言性能对比,C++、Java、Python、LUA、TCC

一直想做开发语言性能对比,刚好有时间都做了给大家参考一下, 编译类:C++和Java表现还不错 脚本类:TCC脚本动态运行C语言,性能比其他脚本快好多... 想玩TCC的同学下载测试包,TCC目录下修改script.c,运行TccTest1.exe即可看到修改效果,无需编译!!! 链接:http://pan.baidu.com/s/1kUVGGwJ 密码:mgpx C++(VS2017) java8.2 Python2.7-3.5.2 aardio(LUA) TCC

iOS开发ARC与MRC下单例的完整写法与通用宏定义

#import "XMGTool.h" /** * 1:ARC下的完整的单例写法:alloc内部会调用+(instancetype)allocWithZone:(struct _NSZone *)zone方法,所以重写该方法,用GCD一次性函数,默认是线程安全的加了一把锁,也可以自己去加锁 @synchronized(self) { if (_instance == nil) { _instance = [super allocWithZone:zone]; } } 2:还要考虑cop

HW3000、SI4432、A7139及目前市面主流的Sub-1G芯片性能对比

HW3000.SI4432.A7139.SX1278.CC1120及目前市面主流的Sub-1G芯片性能对比

使用httpclient实现http链接池与使用HttpURLConnection发送http请求的方法与性能对比

使用httpclient实现http链接池与使用HttpURLConnection发送http请求的方法与性能对比 在项目中需要使用http调用接口,实现了两套发送http请求的方法,一个是使用apache的httpclient提供的http链接池来发送http请求,另一个是使用java原生的HttpURLConnection来发送http请求,并对两者性能进行了对比. 使用httpclient中的链接池发送http请求 使用最新的4.5.2版httpclient进行实现.在maven中引入 <

C正则库做DNS域名验证时的性能对比

C正则库做DNS域名验证时的性能对比 本文对C的正则库regex和pcre在做域名验证的场景下做评测. 验证DNS域名的正则表达式为: "^[0-9a-zA-Z_-]+(\\.[0-9a-zA-Z_-]+)*(\\.[a-zA-Z]{2,}\\.)$" 对于正常DNS请求日志中的6177578条日志做正则验证处理. 1,pcre 评测所用的pcre的版本号是:7.8.3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2