私の質問は、関数のインライン化による最新のブラウザーの最適化に関するものです。この質問に答えるには、V8、JavaScriptCore、SpiderMonkeyコードベースに精通している人が本当に必要だと思います。または、少なくとも、最適化への最新のブラウザアプローチに精通している人。
基本的に、関数のインライン化がいつ使用されるかを予測する方法があるかどうか、および最小限のコード重複でパフォーマンスを最適化するためにそれを活用する方法を知りたいです。
例として、joitempoから次の単純な関数を取り上げましょう。
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function';
if(!isFunction) max = max >>> 0 || 1;
return function limitedFunction() {
if(isFunction ? !max(count) : (count >= max)) return;
count++;
return f.apply(this, arguments);
};
}
この関数は関数を受け取り、f
ラッパー関数を返します。ラッパー関数は、ラッパーを介して元の関数を呼び出すことができる回数を制限します。例:
var foo = limit(function() { console.log('foo'); }, 3);
foo(); // logs 'foo'
foo(); // logs 'foo'
foo(); // logs 'foo'
foo(); // doesn't log anything
foo(); // doesn't log anything
また、(数値の代わりに)2番目の引数としてtrue
またはを返す関数を受け入れます。false
var bar = limit(
function() { console.log('bar'); },
function() { return Math.random() > 0.5 ? true : false }
);
bar(); // randomly logs 'bar' or doesn't log anything
bar(); // randomly logs 'bar' or doesn't log anything
bar(); // randomly logs 'bar' or doesn't log anything
これは非常に単純で些細な例なので、我慢してください。これには重要なケースで実際のアプリケーションがあると思いますが、簡単なケースを使用して、ブラウザーがインライン化を実行する方法または実行できる方法の根本を理解したいと思います。
パフォーマンスを(おそらく)(非常にわずかに)改善できるこの関数を書き直す1つの方法は、返された関数function
を2つのケースに分けることです。1つmax
は関数で、もう1つmax
は数値です。
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function';
if(!isFunction) max = max >>> 0 || 1;
return isFunction
? function limitedFunctionA() {
if(!max(count)) return;
count++;
return f.apply(this, arguments);
}
: function limitedFunctionB() {
if(count >= max) return;
count++;
return f.apply(this, arguments);
};
}
このようにして、毎回発生するかどうかisFunction
を確認するチェックが呼び出されますが、戻るかどうかが決定されたときに1回だけ呼び出されます。ただし、冗長なコードがあるため、これは理想的ではありません。true
false
limitedFunction
limitedFunctionA
limitedFunctionB
私の質問は、次の書き直しに関するものです。
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function',
check = isFunction
? function() { return !max(count); }
: function() { return count >= max; };
if(!isFunction) max = max >>> 0 || 1;
return function limitedFunction() {
if(check()) return;
count++;
return f.apply(this, arguments);
};
}
だからここに私の質問があります...現代のブラウザは回るのに十分賢いですか
if(check()) return;
の中へ
if(!max(count)) return;
いつisFunction
が真であり、
if(count >= max) return;
いつisFunction
偽ですか?...余分な関数を呼び出す必要をなくし、check()
毎回不必要に余分な関数をスタックにスローします。