10

如果我写有任何性能提升

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

代替

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

??

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

4

2 回答 2

14

如果您尝试一下(菜单->产品->生成输出->程序集文件)-您会注意到在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 %@!"
于 2013-08-15T09:59:58.493 回答
13

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

考虑到这一点

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

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

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

嘿编译器,格式字符串总是一样的,所以不要费心分配它不止一次

答案是:

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

笔记

如果您仍然持怀疑态度,您可以查看程序集(查看 Dirk 的回答),但让我在这里给您一条建议:不要对此类性能问题大发雷霆。

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

总结一下:让编译器做它的工作,你做你的工作,即编写可读和可维护的代码。

于 2013-08-15T10:05:11.963 回答