NSString - 静态还是内联?是否有任何性能提升?

时间:2013-08-15 09:40:06

标签: iphone ios objective-c nsstring

如果我写

,是否有任何性能提升
- (NSString *)helloStringWithName:(NSString *)name
    static NSString *formatString = @"Hello %@!";
    return [NSString stringWithFormat:formatString, name];
}

而不是

- (NSString *)helloStringWithName:(NSString *)name
    return [NSString stringWithFormat:@"Hello %@!", name];
}

...

如果我猜测我会认为后者是在每次代码运行时创建并自动释放的,但我想编译器足够聪明,知道这里做了什么..

2 个答案:

答案 0 :(得分:15)

如果你试试这个(菜单 - >产品 - >生成输出 - >组装文件) - 你会注意到clang下几乎相同的输出 - 由于额外的变量赋值而只有很小的变化。调试信息离开。

所以简而言之 - 没有真正的区别;虽然静态的一个可能更容易调试我猜。

    .align  4, 0x90
"-[Foo helloStringWithName1:]":         ## @"\01-[Foo helloStringWithName1:]"
    .cfi_startproc
Lfunc_begin0:
    .loc    1 15 0                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:15:0
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    subq    $48, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, %rdi
    callq   _objc_retain
    movq    %rax, -24(%rbp)
    .loc    1 17 5 prologue_end     ## /Users/dirkx/tmp/ccccc/ccccc/main.m:17:5
Ltmp5:
    movq    L_OBJC_CLASSLIST_REFERENCES_$_(%rip), %rax
    movq    "-[Foo helloStringWithName1:].formatString"(%rip), %rdx
    movq    -24(%rbp), %rcx
    movq    L_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
    movq    %rax, %rdi
    movb    $0, %al
    callq   _objc_msgSend
    movq    %rax, %rdi
    callq   _objc_retainAutoreleasedReturnValue
    movabsq $0, %rsi
    leaq    -24(%rbp), %rcx
    movl    $1, -28(%rbp)
    .loc    1 18 1                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:18:1
    movq    %rcx, %rdi
    movq    %rax, -40(%rbp)         ## 8-byte Spill
    callq   _objc_storeStrong
Ltmp6:
    .loc    1 18 1                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:18:1
    movq    -40(%rbp), %rax         ## 8-byte Reload
    movq    %rax, %rdi
    callq   _objc_autoreleaseReturnValue
    .loc    1 17 5                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:17:5
Ltmp7:
    addq    $48, %rsp
    popq    %rbp
    ret
Ltmp8:
Lfunc_end0:
    .cfi_endproc

    .align  4, 0x90
"-[Foo helloStringWithName2:]":         ## @"\01-[Foo helloStringWithName2:]"
    .cfi_startproc
Lfunc_begin1:
    .loc    1 20 0                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:20:0
## BB#0:
    pushq   %rbp
Ltmp11:
    .cfi_def_cfa_offset 16
Ltmp12:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp13:
    .cfi_def_cfa_register %rbp
    subq    $48, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, %rdi
    callq   _objc_retain
    leaq    L__unnamed_cfstring_2(%rip), %rdx  <-------------------- 
    movq    %rax, -24(%rbp)
    .loc    1 21 5 prologue_end     ## /Users/dirkx/tmp/ccccc/ccccc/main.m:21:5
Ltmp14:
    movq    L_OBJC_CLASSLIST_REFERENCES_$_(%rip), %rax
    movq    -24(%rbp), %rcx
    movq    L_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
    movq    %rax, %rdi
    movb    $0, %al
    callq   _objc_msgSend
    movq    %rax, %rdi
    callq   _objc_retainAutoreleasedReturnValue
    movabsq $0, %rsi
    leaq    -24(%rbp), %rcx
    movl    $1, -28(%rbp)
    .loc    1 22 1                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:22:1
    movq    %rcx, %rdi
    movq    %rax, -40(%rbp)         ## 8-byte Spill
    callq   _objc_storeStrong
Ltmp15:
    .loc    1 22 1                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:22:1
    movq    -40(%rbp), %rax         ## 8-byte Reload
    movq    %rax, %rdi
    callq   _objc_autoreleaseReturnValue
    .loc    1 21 5                  ## /Users/dirkx/tmp/ccccc/ccccc/main.m:21:5
Ltmp16:
    addq    $48, %rsp
    popq    %rbp
    ret
Ltmp17:
Lfunc_end1:
    .cfi_endproc

作为关键参考:

Lfunc_end2:
    .cfi_endproc

    .section    __DATA,__data
    .align  3                       ## @"\01-[Foo helloStringWithName1:].formatString"
"-[Foo helloStringWithName1:].formatString":
    .quad   L__unnamed_cfstring_

    .section    __TEXT,__cstring,cstring_literals
l_.str:                                 ## @.str
    .asciz   "Hello 1 %@!"

    .section    __TEXT,__cstring,cstring_literals
l_.str1:                                ## @.str1
    .asciz   "Hello 2 %@!"

答案 1 :(得分:14)

Objective-C中的字符串文字是在编译时分配的,因此您无法合理地获得任何性能。

考虑这个

NSString * str = @"Hello";    
NSString * str2 = @"Hello";

NSLog(@"%p", str);  // => 0x860358
NSLog(@"%p", str2); // => 0x860358

因此,如果你的意图是这样说:

嘿编译器,格式字符串总是一样的,所以不要再多次分配

答案是:

多好,告诉我一些我不知道的事情

注意

如果你仍然持怀疑态度,你可以看一下大会(看看Dirk的答案),但是请允许我在这里给你一些建议:不要对这些性能问题感到头疼。

使用NSString和高级抽象作为对象的开销在你的程序性能中绝对占主导地位,所以即使你每串获得一个纳秒,你也不会合理地注意到这一点。 正如你理所当然地怀疑的那样,编译器已经足够聪明,可以处理这些细节。

将它包装起来:让编译器完成它的工作而你自己完成它,即编写可读和可维护的代码。