C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

JavaScriptのハッシュオブジェクトに繰り返しアクセスする際のコストを減らす為の唯一の方法

本当は2つあると思っていた。先の記事と同様に結果とソースから。

結果

{ time: 109, title: 'direct' }
{ time: 116, title: 'array depth-1' }
{ time: 144, title: 'array depth-2' }
{ time: 169, title: 'array depth-3' }
{ time: 191, title: 'array depth-4' }
{ time: 201, title: 'array depth-5' }
{ time: 1400, title: 'with depth-0(direct)' }
{ time: 1396, title: 'with depth-0(array depth-1)' }
{ time: 1401, title: 'with depth-0(array depth-2)' }
{ time: 1469, title: 'with depth-0(array depth-3)' }
{ time: 1405, title: 'with depth-0(array depth-4)' }
{ time: 1396, title: 'with depth-0(array depth-5)' }
{ time: 94, title: 'direct in function scope' }
{ time: 93, title: 'array depth-1 in function scope' }
{ time: 94, title: 'array depth-2 in function scope' }
{ time: 97, title: 'array depth-3 in function scope' }
{ time: 94, title: 'array depth-4 in function scope' }
{ time: 93, title: 'array depth-5 in function scope' }
{ time: 115, title: 'array depth-1(5) in function scope' }
{ time: 151, title: 'array depth-2(5) in function scope' }
{ time: 170, title: 'array depth-3(5) in function scope' }
{ time: 191, title: 'array depth-4(5) in function scope' }
{ time: 211, title: 'array depth-5(5) in function scope' }
LH-MAIN /tmp% node --version
v0.6.13
LH-MAIN /tmp% uname -a 
Linux LH-MAIN 3.2.11-1-ARCH #1 SMP PREEMPT Thu Mar 15 09:19:02 CET 2012 x86_64 AMD Phenom(tm) II X4 940 Processor AuthenticAMD GNU/Linux

ソース

var v = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';

var
  a1 = [v],
  a2 = [[v]],
  a3 = [[[v]]],
  a4 = [[[[v]]]],
  a5 = [[[[[v]]]]];

var benchmark = function(f, title){
  var a = new Date();
  for(var n = 10*1000*1000; n; --n)
    f();
  var b = new Date();
  console.log( { time:b-a, title:title } );
};

benchmark( function(){ var a = v; }, 'direct' );
benchmark( function(){ var a = a1[0]; }, 'array depth-1');
benchmark( function(){ var a = a2[0][0]; }, 'array depth-2');
benchmark( function(){ var a = a3[0][0][0]; }, 'array depth-3');
benchmark( function(){ var a = a4[0][0][0][0]; }, 'array depth-4');
benchmark( function(){ var a = a5[0][0][0][0][0]; }, 'array depth-5');

with({x:v})
  benchmark( function(){ var a = x;}, 'with depth-0(direct)');
with({x:a1[0]})
  benchmark( function(){ var a = x;}, 'with depth-0(array depth-1)');
with({x:a2[0][0]})
  benchmark( function(){ var a = x;}, 'with depth-0(array depth-2)');
with({x:a3[0][0][0]})
  benchmark( function(){ var a = x;}, 'with depth-0(array depth-3)');
with({x:a4[0][0][0][0]})
  benchmark( function(){ var a = x;}, 'with depth-0(array depth-4)');
with({x:a5[0][0][0][0][0]})
  benchmark( function(){ var a = x;}, 'with depth-0(array depth-5)');

(function(){
  var y = v;
  benchmark(function(){ var a = y;}, 'direct in function scope');
})();

(function(){
  var y = a1[0];
  benchmark(function(){ var a = y;}, 'array depth-1 in function scope');
})();

(function(){
  var y = a2[0][0];
  benchmark(function(){ var a = y;}, 'array depth-2 in function scope');
})();

(function(){
  var y = a3[0][0][0];
  benchmark(function(){ var a = y;}, 'array depth-3 in function scope');
})();

(function(){
  var y = a4[0][0][0][0];
  benchmark(function(){ var a = y;}, 'array depth-4 in function scope');
})();

(function(){
  var y = a5[0][0][0][0][0];
  benchmark(function(){ var a = y;}, 'array depth-5 in function scope');
})();

(function(){
  var y = a5[0][0][0][0];
  benchmark(function(){ var a = y[0];}, 'array depth-1(5) in function scope');
})();

(function(){
  var y = a5[0][0][0];
  benchmark(function(){ var a = y[0][0];}, 'array depth-2(5) in function scope');
})();
(function(){
  var y = a5[0][0];
  benchmark(function(){ var a = y[0][0][0];}, 'array depth-3(5) in function scope');
})();
(function(){
  var y = a5[0];
  benchmark(function(){ var a = y[0][0][0][0];}, 'array depth-4(5) in function scope');
})();
(function(){
  var y = a5;
  benchmark(function(){ var a = y[0][0][0][0][0];}, 'array depth-5(5) in function scope');
})();

つまり?

ゲームを作る場合などリアルタイム性の高いJavaScriptコンテンツを作ろうと言う場合などでハッシュオブジェクトのアクセスコストを最適化する唯一の方法は、

  • ハッシュオブジェクトの中身をプログラマーが意図して処理系が容易にアクセスできる様に明示的に変数に束縛するしかない。
    • しかもその方法で間違ってもwithを使ってローカルスコープを作ってはならない。
    • つまり無名関数を作りハッシュオブジェクトへのアクセスコストを下げる為のローカル変数を用いて繰り返し処理などを行う事で最適化するしかない。