6

私のコードには、一連のピクセル座標を含むオブジェクトがあります。出力が常にキャッシュされるとは限らない 60fps ゲームで使用されるため、このオブジェクトのパフォーマンスは重要です。

実験とベンチマークの後、型なし配列を使用する場合、3D 配列が実装の最速の方法であることが判明しました。

var PixelCollection = function() {
    this.pixels = [];
};

PixelCollection.prototype = {
    add: function(x, y) {
        var pixels = this.pixels;
        if (pixels[y]) {
            pixels[y].push(x);
        } else {
            pixels[y] = [x];
        }
    },
    each: function(callback) {
        var pixels = this.pixels;
        for (var y = 0, m = pixels.length; y < m; y++) {
            var row = pixels[y];
            if (row) {
                for (var i = 0, mm = row.length; i < mm; i++) {
                    callback(row[i], y);
                }
            }
        }
    }
};

状況によっては、オブジェクトの速度が十分でないためUint8Array、2D 配列を使用して実装を試みました。

var WIDTH = 255;
var HEIGHT = 160;

PixelCollection = function() {
    this.pixels = new Uint8Array(WIDTH * HEIGHT);
};

PixelCollection.prototype = {
    add: function(x, y) {
        this.pixels[WIDTH * y + x] = 1;
    },
    each: function(callback) {
        var pixels = this.pixels;
        for (var i = 0, m = pixels.length; i < m; i++) {
            if (pixels[i]) {
                callback(i % WIDTH, Math.floor(i / WIDTH));
            }
        }
    }
}

これは遅くなります。- への書き込みと s からの読み取りが高速であるため、高速になると思いましたがUint8array、すべての PixelCollection オブジェクトに対して巨大なオブジェクトを作成しているため、すべてのピクセルを反復処理するのに時間がかかるため、ピクセルの取得が大幅に遅くなります。(注:型なし配列を使用して上記の実装も試しました。かなり遅いです)

通常、PixelCollection にはすべてのピクセルが設定されているわけではありません。ただし、境界ボックスはキャンバス全体にまたがる可能性があるため、この大きなバッファーを使用して配列を作成する必要があります。

しかし、それを回避する方法があるかもしれません。1 つの大きな共有バッファーを作成し、PixelCollection ごとにバイト オフセットを使用できます。そのため、PixelCollectionP1が 100 バイトを占める場合、PixelCollectionP2はバイト オフセット 100 から開始されます。これによりメモリがより効率的に使用されますが、PixelCollection が使用するすべてのバイトの範囲を追跡する必要があります (これは C が「ポインター」と呼ぶものですか?) .

厄介な部分:P1のバウンディング ボックスが拡大すると、 のP2スペースを確保するために移動する必要がありP1ます。また、共有バッファーに安全なバッファー サイズを設定する必要があるため、必要なメモリ量を安全に推測する必要があります。

これを実装することは可能ですが、多くの時間と試行錯誤が必要です。

ですから、これを始める前に、それは良い方法だと思いますか? これを行うためのより良い方法または簡単な方法はありますか? 私が学ぶことができる実装例を知っていますか?

編集:最適化を試してみたい場合に備えて、jsperf を追加しました。
最適化の優れたアイデアがある場合は、この jsperf に追加してください。

4

1 に答える 1