Stringメソッドのプロトタイプをいくつかのユーティリティメソッドで拡張したかったのです。それはうまくいったが、パフォーマンスは驚くほど低かった。文字列を関数に渡すことは、同じことをしているString.prototype
メソッドをオーバーライドするよりも10倍高速です。これが実際に起こることを確かめるために、私は非常に単純なcount()
関数とそれに対応するメソッドを作成しました。 String.prototypeのパフォーマンスを拡張すると、関数呼び出しが10倍高速になることがわかります。
function count(str, char) {
var n = 0;
for (var i = 0; i < str.length; i++) if (str[i] == char) n++;
return n;
}
String.prototype.count = function (char) {
var n = 0;
for (var i = 0; i < this.length; i++) if (this[i] == char) n++;
return n;
}
String.prototype.count_reuse = function (char) {
return count(this, char)
}
String.prototype.count_var = function (char) {
var str = this;
var n = 0;
for (var i = 0; i < str.length; i++) if (str[i] == char) n++;
return n;
}
// Here is how I measued speed, using Node.js 6.1.0
var STR ='0110101110010110100111010011101010101111110001010110010101011101101010101010111111000';
var REP = 1e3//6;
console.time('func')
for (var i = 0; i < REP; i++) count(STR,'1')
console.timeEnd('func')
console.time('proto')
for (var i = 0; i < REP; i++) STR.count('1')
console.timeEnd('proto')
console.time('proto-reuse')
for (var i = 0; i < REP; i++) STR.count_reuse('1')
console.timeEnd('proto-reuse')
console.time('proto-var')
for (var i = 0; i < REP; i++) STR.count_var('1')
console.timeEnd('proto-var')
結果:
func: 705 ms
proto: 10011 ms
proto-reuse: 10366 ms
proto-var: 9703 ms
あなたは差は劇的で見ることができるように。
メソッド呼び出しのパフォーマンスが無視できるほど遅く、関数コード自身がメソッドの処理速度が遅いことがわかります。
function count_dummy(str, char) {
return 1234;
}
String.prototype.count_dummy = function (char) {
return 1234; // Just to prove that accessing the method is not the bottle-neck.
}
console.time('func-dummy')
for (var i = 0; i < REP; i++) count_dummy(STR,'1')
console.timeEnd('func-dummy')
console.time('proto-dummy')
for (var i = 0; i < REP; i++) STR.count_dummy('1')
console.timeEnd('proto-dummy')
console.time('func-dummy')
for (var i = 0; i < REP; i++) count_dummy(STR,'1')
console.timeEnd('func-dummy')
結果:
func-dummy: 0.165ms
proto-dummy: 0.247ms
(1E8のような)巨大な繰り返しでメソッドを試作が機能よりも10倍の倍遅くであると証明する、これはこのケースでは無視することができます。
var A = { count: 1234 };
function getCount(obj) { return obj.count }
A.getCount = function() { return this.count }
console.time('func')
for (var i = 0; i < 1e9; i++) getCount(A)
console.timeEnd('func')
console.time('method')
for (var i = 0; i < 1e9; i++) A.getCount()
console.timeEnd('method')
結果::
func: 1689.942ms
method: 1674.639ms
あなたが関数に渡したり、メソッドを呼び出したときに、単純な汎用オブジェクトがほぼ同じ行うため
このすべては、唯一のStringオブジェクトに関連している可能性があり私はStackoverflowとbingingで検索してきましたが、「名前空間を汚染するためStringまたはArrayを拡張しないでください」という推奨事項(私の特定のプロジェクトでは問題ではない)は、メソッドの実行に関連するものは何も見つかりませんfunctioと比較してns。だから、私は単に、追加されたメソッドのパフォーマンス低下のためにStringオブジェクトを拡張することを忘れてはならないのでしょうか?
感謝しますが:
その後、あなたの実装を修正。新しいインスタンスを取得します。 BTWの結果は同じです。 –