如果我写
,是否有任何性能提升- (NSString *)helloStringWithName:(NSString *)name
static NSString *formatString = @"Hello %@!";
return [NSString stringWithFormat:formatString, name];
}
而不是
- (NSString *)helloStringWithName:(NSString *)name
return [NSString stringWithFormat:@"Hello %@!", name];
}
...
如果我猜测我会认为后者是在每次代码运行时创建并自动释放的,但我想编译器足够聪明,知道这里做了什么..
答案 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
和高级抽象作为对象的开销在你的程序性能中绝对占主导地位,所以即使你每串获得一个纳秒,你也不会合理地注意到这一点。
正如你理所当然地怀疑的那样,编译器已经足够聪明,可以处理这些细节。
将它包装起来:让编译器完成它的工作而你自己完成它,即编写可读和可维护的代码。