performance - How do I use a typed array using a shared buffer efficiently in JavaScript? -
in code have object contains series of pixel coordinates. performance of object critical because it's being used in 60fps game output cannot cached.
after experimentation , benchmarking, 3d array proved fastest way of implementing when using untyped arrays:
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; (var y = 0, m = pixels.length; y < m; y++) { var row = pixels[y]; if (row) { (var = 0, mm = row.length; < mm; i++) { callback(row[i], y); } } } } };
in situations, object not fast enough, tried uint8array
implementation, using 2d array:
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; (var = 0, m = pixels.length; < m; i++) { if (pixels[i]) { callback(i % width, math.floor(i / width)); } } } }
this slower. thought faster because writing - , reading uint8array
s faster, since i'm creating huge object every pixelcollection object, retrieving pixels way slower because takes longer iterate on pixels. (note: tried implementation above untyped array: lot slower)
a pixelcollection typically not have pixels set. however, bounding box may span entire canvas need create array using buffer big.
there may way around though. can create 1 big shared buffer , use byte offset every pixelcollection. when pixelcollection p1
take 100 bytes, pixelcollection p2
start @ byte offset 100. uses memory more efficiently, need keep track of range of bytes every pixelcollection uses (is c calls "pointers"?).
annoying part: when p1
's bounding box expands, need shift p2
make space p1
. , need set safe buffer size shared buffer, need make safe guesstimation of how memory needs.
implementing possible, require lots of time, trial , error.
so before start on this: seem way it? there better or simpler ways this? know example implementations learn from?
edit: i added jsperf in case want try hand @ optimization.
please add jsperf if have brilliant idea optimization.
by slower guess mean running pixelcollection.each
? second example might slower if there aren't many points set 1, still checks possible locations whilst first runs through added points. if want every possible nanosecond @ cost (in case memory), can pre-allocate maximum size in 2 uint8array
s , separately keep track of size.
var width = 255; var height = 160; var pixelcollection = function() { this.pixels.length = 0; this.pixels.x = new uint8array(width * height); this.pixels.y = new uint8array(width * height); }; pixelcollection.prototype = { add: function(x, y) { this.pixels.x[this.pixels.length] = x; this.pixels.y[this.pixels.length] = y; this.pixels.length++; }, each: function(callback) { var pixels = this.pixels; (var = 0; < this.pixels.length; i++) { callback(this.pixels.x[i], this.pixels.y[i]); } } };
if know limit number of additions pixelcollection have can reduce memory usage. combine 2 arrays 1 double length alternating x , y values.
however, if want able remove individual points method gets tricky, it's unlikely faster first method @pudge601's loop change.
Comments
Post a Comment