10

私は関数にオプションの引数を持っていることがよくありますが、いくつかのテストでは、FirefoxとSafari(70-95%)でそれらのパフォーマンスに大きな打撃を与えています。不思議なことに、未定義のリテラル値を渡してもペナルティはありません。ここで何が起こっているのでしょうか?それらは本質的に関数に対してローカルであるため、スコープチェーンの問題であるとは思いませんでした。すべてのオプションの引数にundefinedを渡し始めますか?

jsPerf: http: //jsperf.com/function-undefined-args/2

4

2 に答える 2

5

このような関数の場合:

function threeArgs(x, y, z) {
  return x + y + z;
}

それは次のように呼び出されます:

threeArgs(1, 2, 3);

オプティマイザーは、コードをまったく生成しないという選択を自由に行うことができます。関数は単純にパラメーター値を参照し、単純な式の結果を返すため、副作用がないと判断するのは非常に簡単です。戻り値は無視されるため、ランタイムが何かを行う理由はまったくありません。

それを超えて、コードが次の場合:

something += threeArgs(1, 2, 3);

オプティマイザーは、以下とほぼ同等のコードを生成することを決定する場合があります。

something += 6;

なんで?呼び出しは数値定数を使用して行われたため、コード生成時にそれらを安全に折りたたむことができます。数字は奇妙なので保守的かもしれませんが、ここではすべて整数なので、これで十分です。そうでない場合でも、関数を安全にインライン化できます。

something += 1 + 2 + 3;

ただし、パラメーターが欠落している場合、オプティマイザーが救済され、実際の関数呼び出しが生成される可能性があります。このような単純な関数の場合、関数呼び出しのオーバーヘッドがパフォーマンスの大きな違いを簡単に説明できます。

テストで定数の代わりに変数を使用し、関数の戻り値を実際に使用することで、オプティマイザーを「混乱」させ、呼び出しをスキップしたり、結果を事前に計算したりしないようにすることができますが、インライン化。その理由であなたの結果はまだ興味深いと思います.(とにかく今日の時点で)これらのオプティマイザは関数が呼び出される方法に敏感であるという事実を明らかにしています.

于 2012-09-30T16:12:42.263 に答える
2

パフォーマンスの違いを説明できるのは、引数が関数オブジェクトに渡される方法、つまりオブジェクトを介してだと思いargumentsます。引数を渡さない場合、JS は引数オブジェクトをスキャンして、指定された引数のいずれかを探します。それらが未定義の場合は、argumentsプロトタイプ チェーンが までスキャンされObject.prototypeます。それらすべてに目的のプロパティがない場合、JS は を返しundefinedます。一方、undefined を明示的に渡すと、arguments オブジェクトのプロパティとして直接設定されます。

function foo(arg)
{
    console.log(arguments.hasOwnProperty('0'));
}
foo();//false'
foo('bar');//true
foo(undefined);//true

それが、 undefined を明示的に渡す方が高速になる傾向がある理由だと思います。

于 2012-09-30T16:10:57.303 に答える