JScript高速化(5)

前回は、
単純なオブジェクトの生成と
polyオブジェクトの生成との間に大きな差があることが分かった。
この差はなんなのかつきつめていこう。
そのために、単純なオブジェクトから少しずつプロパティを追加していく。


// 1597ms
function poly() {
this.a = [ 0 ];

this.copy = poly_copy;
}

function poly_copy() {
;
}

に対して、copyメソッドだけ実装しよう。


// コピー
function poly_copy() {
var r = new poly();
for(var i = 0; i < this.a.length; i++)
r.a[i] = this.a[i];
return r;
}

それから、こう書いて9次の多項式を作っておく。


var p = new poly();
for(var i = 0; i < 10; i++)
p.a[i] = i;

4569ms。
3sも遅くなるはずないんだけど。
その半分くらいのはず。
試しに配列の代入をなくしてみると、


// 1925ms
function poly_copy() {
var r = new poly();
for(var i = 0; i < 0; i++)
r.a[i] = this.a[i];
return r;
}

newのコストを考えれば、これでも速いくらい。
プロパティのアクセスを減らしてみるか。


// 3896ms
function poly_copy() {
var r = new poly();
var ra = r.a;
var a = this.a;
for(var i = a.length - 1; i >= 0; i--)
ra[i] = a[i];
return r;
}

確かに速くなったけど。
これよりは速くならないかな。
じゃあ、コンストラクタにこれだけくっつけたら?


// 5382ms
var args = poly.arguments;
if(args.length == 0)
this.a = [ 0 ];
else {
this.a = [ ];
for(var i = 0; i < args.length; i++) {
var b = args[i];
if(typeof b == "number")
this.a.push(b);
else if(b instanceof Array) {
for(var j = 0; j < b.length; j++)
this.a.push(b[j]);
}
}
}

なぜこれで1.5msものコストが。
じゃあこれだけにすると?


// 5361ms
var args = poly.arguments;
this.a = [ 0 ];

Argumentsオブジェクトへのアクセスが遅いってことか。
そんなバカなというカンジだが。
困ったな。どう回避する?


// 3918ms
if(a == undefined)
this.a = [ 0 ];
else {
this.a = [ ];
var args = poly.arguments;
for(var i = 0; i < args.length; i++) {
var b = args[i];
if(typeof b == "number")
this.a.push(b);
else if(b instanceof Array) {
for(var j = 0; j < b.length; j++)
this.a.push(b[j]);
}
}
}

これでうまくいった。
引数ありのときは依然遅いが、
そういう場合は少ないはずなので、それほど問題ないだろう。