admin管理员组文章数量:1410730
I've build my own flip
mand and, well its slow and takes forever. I would like to know if javascript has a blit
or memcpy
style mand. Right now I'm going through item by item with for loops to do a copy and it takes "forever".
Here is a example use of my flip function. I'm running 3 layers, only 1 if full height, with 3 simple animations and the fps it topped out at about 35 FPS. Ideally 3 layes should be topped out at far far higher FPS, in the 200+ range I would expect.
v:36.8 l0:36.8 l1:57.8 l2:36.8 The layer's FPS are the rendering to their buffers, the v is the rendering to the canvas with the flip
function. (These FPS are from Chrome on a mac)
v = the screen update, the main flip function listed below.
l0 = The bottom fire, its a full height layer
l2 = The static noise, its a 1/2 height layer
l3 = The top fire, its a 1/4 height layet
Imagine having 9 or 10 layers, the FPS would drop like a stone. In FF version 12 its already unusable... not even double digit FPS rates. Opera is at least double digets.
v:4.2 l0:4.2 l1:4.2 l2:4.2 (FF 12 OSX)
v:15.5 l0:15.5 l1:15.5 l2:15.5 (Opera latest OSX)
My flip function
flip : function() {
var fps = '';
// Combine the layers onto the back buffer
for (var l = 0; l < this.layers.length; l++)
{
fps += 'l' + l + ':' + this.layers[l].fps.toFixed(1) + ' ';
var layerWidth = this.layers[l].options.width;
var layerHeight = this.layers[l].options.height;
for (var x = 0; x < layerWidth; x++)
{
for (var y = 0; y < layerHeight; y++)
{
var index = (y*this.layers[l].options.width + x)*4;
var r = this.layers[l].buffer[index+0];
var g = this.layers[l].buffer[index+1];
var b = this.layers[l].buffer[index+2];
var a = this.layers[l].buffer[index+3];
if (r|g|b|a != 0) {
this.buffer.data[index+0] = r;
this.buffer.data[index+1] = g;
this.buffer.data[index+2] = b;
this.buffer.data[index+3] = a;
}
}
}
}
fps = 'v:' + this.fps.toFixed(1) + ' ' + fps;
this.$fps.html(fps);
// blit the buffer
this.context.putImageData(this.buffer, 0, 0);
// Calculate fps
var now = new Date;
var thisFrameFPS = 1000 / (now - this.last);
this.fps += (thisFrameFPS - this.fps) / 50;
this.last = now;
var t = this;
setTimeout(function() {t.flip.apply(t);}, this.speed);
}
I've build my own flip
mand and, well its slow and takes forever. I would like to know if javascript has a blit
or memcpy
style mand. Right now I'm going through item by item with for loops to do a copy and it takes "forever".
Here is a example use of my flip function. I'm running 3 layers, only 1 if full height, with 3 simple animations and the fps it topped out at about 35 FPS. Ideally 3 layes should be topped out at far far higher FPS, in the 200+ range I would expect.
v:36.8 l0:36.8 l1:57.8 l2:36.8 The layer's FPS are the rendering to their buffers, the v is the rendering to the canvas with the flip
function. (These FPS are from Chrome on a mac)
v = the screen update, the main flip function listed below.
l0 = The bottom fire, its a full height layer
l2 = The static noise, its a 1/2 height layer
l3 = The top fire, its a 1/4 height layet
Imagine having 9 or 10 layers, the FPS would drop like a stone. In FF version 12 its already unusable... not even double digit FPS rates. Opera is at least double digets.
v:4.2 l0:4.2 l1:4.2 l2:4.2 (FF 12 OSX)
v:15.5 l0:15.5 l1:15.5 l2:15.5 (Opera latest OSX)
My flip function
flip : function() {
var fps = '';
// Combine the layers onto the back buffer
for (var l = 0; l < this.layers.length; l++)
{
fps += 'l' + l + ':' + this.layers[l].fps.toFixed(1) + ' ';
var layerWidth = this.layers[l].options.width;
var layerHeight = this.layers[l].options.height;
for (var x = 0; x < layerWidth; x++)
{
for (var y = 0; y < layerHeight; y++)
{
var index = (y*this.layers[l].options.width + x)*4;
var r = this.layers[l].buffer[index+0];
var g = this.layers[l].buffer[index+1];
var b = this.layers[l].buffer[index+2];
var a = this.layers[l].buffer[index+3];
if (r|g|b|a != 0) {
this.buffer.data[index+0] = r;
this.buffer.data[index+1] = g;
this.buffer.data[index+2] = b;
this.buffer.data[index+3] = a;
}
}
}
}
fps = 'v:' + this.fps.toFixed(1) + ' ' + fps;
this.$fps.html(fps);
// blit the buffer
this.context.putImageData(this.buffer, 0, 0);
// Calculate fps
var now = new Date;
var thisFrameFPS = 1000 / (now - this.last);
this.fps += (thisFrameFPS - this.fps) / 50;
this.last = now;
var t = this;
setTimeout(function() {t.flip.apply(t);}, this.speed);
}
Share
Improve this question
asked May 26, 2012 at 5:37
Justin808Justin808
21.6k48 gold badges166 silver badges273 bronze badges
3 Answers
Reset to default 2There is a memcpy.js that uses TypedArray.prototype.subarray() if available.
The browser support is good and even IE10 have subarray
.
function memcpy (src, srcOffset, dst, dstOffset, length) {
var i
src = src.subarray || src.slice ? src : src.buffer
dst = dst.subarray || dst.slice ? dst : dst.buffer
src = srcOffset ? src.subarray ?
src.subarray(srcOffset, length && srcOffset + length) :
src.slice(srcOffset, length && srcOffset + length) : src
if (dst.set) {
dst.set(src, dstOffset)
} else {
for (i=0; i<src.length; i++) {
dst[i + dstOffset] = src[i]
}
}
return dst
}
As of 2024, there is Array.copyWithin or TypedArray.copyWithin which is explicitly stated as:
The [Array.]copyWithin() method works like C and C++'s memmove, and is a high-performance method to shift the data of an Array. This especially applies to the TypedArray method of the same name.
More specifically:
The sequence is copied and pasted as one operation; the pasted sequence will have the copied values even when the copy and paste region overlap.
Your code can be improved, but I doubt that the speedup will be significant.
Here's what I came up with, note it is untested. I have assumed that the order of processing the layers is not significant, if it is replace the first for loop with your version.
function flip () {
var fps = '';
// Combine the layers onto the back buffer
for (var l = this.layers.length; l--;) {
fps += 'l' + l + ':' + this.layers[l].fps.toFixed (1) + ' ';
var layerWidth = this.layers[l].options.width;
var layerHeight = this.layers[l].options.height;
for (var index = 0, x = layerWidth; x--;) {
for (var y = layerHeight; y--; index += 4) {
var r = this.layers[l].buffer[index+0];
var g = this.layers[l].buffer[index+1];
var b = this.layers[l].buffer[index+2];
var a = this.layers[l].buffer[index+3];
if (r|g|b|a != 0) {
this.buffer.data[index+0] = r;
this.buffer.data[index+1] = g;
this.buffer.data[index+2] = b;
this.buffer.data[index+3] = a;
}
}
}
}
};
On the assumption that the r,g,b and a are all 8 bit quantiites you could consider packing them into a single int. That would reduce the processing in the inner loop. Even more efficient would be to use the new arrayBuffer facilities
本文标签: performanceDoes javascript have a blit or memcpy commandStack Overflow
版权声明:本文标题:performance - Does javascript have a blit or memcpy command? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744943240a2633617.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论