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 に答える