1

私が行った場合:

foos[i] = [[Foo alloc] init];
foos[i].prop = @"bar";
[foos[i] baz];

...それは以下よりも効率的ではありません:

Foo *foo = [[Foo alloc] init];
foo.prop = @"bar";
[foo baz];
foos[i] = foo;

またはそれらは同等ですか?

4

3 に答える 3

2

これらは同等ではありませんが、最適化コンパイラがまったく同じバイナリコードを生成する可能性があるほど十分に近いものです。

そうでない場合でも、違いを測定するのに苦労します(foos非常に高価なC ++クラスでない限りoperator[])。プロファイラーが別の言い方をするまで—このコードの最適化は時期尚早です。

于 2012-08-25T09:21:06.473 に答える
1

配列が単純なC配列(Foo * array[11];)の場合、パフォーマンスに大きな影響はありません。

配列がNSMutableArray(または別の添字可能なNSタイプ)の場合、メソッドの実装を繰り返し呼び出す必要があるため(短絡ディスパッチを使用)、オーバーヘッドが発生します。一部の人はそれをマイクロ最適化と見なすでしょうが。この場合、コンパイラーは実装が何を返すかを知ることができないため、呼び出しを省略することはできません。


基本的な実時間の結果は次のとおりです。

MRC:

NSArray:27秒

Cアレイ:18秒

アーク:

NSArray:31秒

Cアレイ:18秒

およびプログラム(ARCをテストするために明らかなARC変更を実行できます):

const int NIter = 10000;

__attribute__((noinline)) void fn1() {
  @autoreleasepool {
    NSMutableArray * foos = [NSMutableArray array];
    for (size_t idx = 0; idx < NIter; ++idx) {
      NSMutableString * str = [NSMutableString new];
      foos[0] = str;
      [foos[0] length];
      [foos removeAllObjects];
      [str release];
    }
  }
}

__attribute__((noinline)) void fn2() {
  @autoreleasepool {
    NSMutableString * foos[1];
    for (size_t idx = 0; idx < NIter; ++idx) {
      foos[0] = [NSMutableString new];
      [foos[0] length];
      [foos[0] release];
      foos[0] = 0;
    }
  }
}

int main() {
  for (size_t idx = 0; idx < NIter; ++idx) {
    if (UseNSArray) {
      fn1();
    }
    else {
      fn2();
    }
  }
  return 0;
}
于 2012-08-25T09:35:18.550 に答える
0

確かに、コンパイラがそれを最適化しない限り。効率が大幅に低下するかどうかは別の問題であり、コードが他に何をしているかによって異なります。このようなマイクロ最適化について心配することは、この付近で効率の問題の証拠がすでにない限り、一般的に無駄です。

于 2012-08-25T11:44:30.477 に答える