javascript 有 blit 或 memcpy 命令吗?

问题描述 投票:0回答:3

我已经构建了自己的

flip
命令,但是它很慢并且需要很长时间。我想知道 javascript 是否有
blit
memcpy
样式命令。现在我正在用 for 循环逐项进行复制,这需要“永远”。

这里是我的翻转功能的使用示例。我正在运行 3 个图层,如果是全高,则只有 1 个图层,带有 3 个简单的动画,其 fps 最高约为 35 FPS。理想情况下,3 层应该以高得多的 FPS 达到顶峰,在我期望的 200+ 范围内。

v:36.8 l0:36.8 l1:57.8 l2:36.8 图层的 FPS 是对其缓冲区的渲染,v 是使用

flip
函数对画布的渲染。 (这些 FPS 来自 Mac 上的 Chrome)

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

想象一下,如果有 9 或 10 层,FPS 就会像石头一样下降。在 FF 版本 12 中,它已经无法使用......甚至连两位数的 FPS 速率都达不到。 Opera 至少是两位数。

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)

我的翻页功能

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);
}
javascript performance
3个回答
2
投票

有一个 memcpy.js 使用 TypedArray.prototype.subarray()(如果可用)。
浏览器支持很好甚至IE10都有

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
}

0
投票

您的代码可以改进,但我怀疑加速是否会显着。

这是我想出的,请注意它未经测试。我假设如果用您的版本替换第一个 for 循环,则处理层的顺序并不重要。

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;
                }
            }
        }
    }
};

假设 r、g、b 和 a 都是 8 位量,您可以考虑将它们打包到一个 int 中。这将减少内循环中的处理。更有效的是使用新的 arrayBuffer 设施


0
投票

截至 2024 年,有 TypedArray.copyWithin 明确声明为:

[Array.]copyWithin() 方法的工作方式类似于 C 和 C++ 的 memmove,并且是一个 移动数组数据的高性能方法。 尤其是这个 适用于同名的 TypedArray 方法

更具体地说:

将序列复制和粘贴作为一项操作;即使复制和粘贴区域重叠,粘贴的序列也将具有复制的值。

© www.soinside.com 2019 - 2024. All rights reserved.