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

如果我写,是否有任何性能提升

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

代替

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

??

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

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

考虑到这一点

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

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

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

答案是:

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

注意

如果你仍然持怀疑态度,你可以看一下大会(看看Dirk的回答),但是让我在这里给你一个建议:不要对这些性能问题大发雷霆。

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

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

如果你试试这个(菜单 – >产品 – >生成输出 – >组装文件) – 你会注意到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 %@!"