Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 像Pixi.js这样的2D绘图框架是如何使画布绘图更快的?_Javascript_Html_Canvas - Fatal编程技术网

Javascript 像Pixi.js这样的2D绘图框架是如何使画布绘图更快的?

Javascript 像Pixi.js这样的2D绘图框架是如何使画布绘图更快的?,javascript,html,canvas,Javascript,Html,Canvas,我为Javascript画布找到了一个bunnymark 当然,我知道他们的默认渲染器使用的是webGL,但我现在只对本地2D上下文性能感兴趣。我在firefox上禁用了webGL,在生成16500只兔子后,计数器显示FPS为25。我决定编写自己的非常简单的渲染循环,看看Pixi增加了多少开销。令我惊讶的是,我的FPS只有20 我的想法大致相当 因此,我决定研究一下它们的源代码,它们的渲染代码似乎并没有什么神奇之处: do { transform = displayObject.wo

我为Javascript画布找到了一个bunnymark

当然,我知道他们的默认渲染器使用的是webGL,但我现在只对本地2D上下文性能感兴趣。我在firefox上禁用了webGL,在生成16500只兔子后,计数器显示FPS为25。我决定编写自己的非常简单的渲染循环,看看Pixi增加了多少开销。令我惊讶的是,我的FPS只有20

我的想法大致相当

因此,我决定研究一下它们的源代码,它们的渲染代码似乎并没有什么神奇之处:

do  
{
    transform = displayObject.worldTransform;
            ...
    if(displayObject instanceof PIXI.Sprite)
    {

        var frame = displayObject.texture.frame;

        if(frame)
        {
            context.globalAlpha = displayObject.worldAlpha;

            context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);

            context.drawImage(displayObject.texture.baseTexture.source, 
                               frame.x,
                               frame.y,
                               frame.width,
                               frame.height,
                               (displayObject.anchor.x) * -frame.width, 
                               (displayObject.anchor.y) * -frame.height,
                               frame.width,
                               frame.height);
        }                      
    }
奇怪的是,他们似乎在使用一个链表作为渲染循环,两个应用程序上的配置文件都显示,虽然我的版本在每帧分配相同的cpu时间,但它们的实现以峰值形式显示cpu使用情况


不幸的是,我的知识到此为止,我很好奇是否有人能解释一下发生了什么。

我注意到你的版本和Pixi的版本之间的一个区别是:

通过将x/y直接传递到
drawImage
函数,可以在特定坐标处渲染图像:

drawImage(img, x, y, ...);
..而Pixi转换整个画布上下文,然后在0/0(已移位的上下文)处绘制图像:

它们还将更多参数传递给
drawImage
;-dx,dy,dw,dh

我怀疑这就是速度差隐藏的地方。但是,将测试更改为使用相同的“技术”

但还有别的事

我记录了5000只兔子,禁用了WebGL,Pixi的性能实际上比定制的小提琴版本更差

我在Pixi上获得约27 FPS:

小提琴上每秒32-35帧:


这都是在Chrome 33.0.1712.4开发版Mac OS X上完成的。

我认为,这可以归结为代码的“可编译”(可缓存)程度。Chrome和Firefox使用两种不同的JavaScript“编译器”/引擎,我们知道这两种引擎对代码进行不同的优化和缓存

画布操作 使用变换与直接坐标不应产生影响,因为设置变换只会更新矩阵,而矩阵在任何情况下都与矩阵中的任何内容一起使用

虽然位置值的类型可能会影响性能,
float
integer
值相比,但由于您的小提琴和PIXI似乎都只使用浮动,这并不是关键

所以这里我不认为画布是造成差异的原因

变量和属性缓存 (在这个答案的第一个版本中,我无意中过于关注原型方面。我试图了解的本质主要是对象遍历,因此下面的文本有点重新措辞-)

PIXI使用对象属性作为提琴,但PIXI中的这些自定义对象的大小较小,因此与遍历较大对象(如画布或图像)相比,遍历对象树所需的时间更少(如
宽度
属性也将位于此对象的末尾)

由于这个原因(遍历时间),缓存变量是众所周知的经典优化技巧。如今,随着引擎变得更加智能,这种影响变得越来越小,尤其是Chrome中的V8引擎,它似乎能够更好地在内部预测/缓存这些变量,而在Firefox中,不在代码中缓存这些变量似乎仍然有一定的影响

这对性能有影响吗?对于短期操作来说很少,但在画布上绘制16500只兔子是一项艰巨的任务,并且确实可以从中获益(在FF中),因此在这种情况下,任何微观优化都是非常重要的

演示 我将“渲染器”原型化,以便更接近PIXI,并缓存对象属性。这在Firefox中带来了性能爆发:

我用了一台速度慢的电脑(来衡量影响),它以每秒5帧的速度运行你的小提琴。在缓存值后,它以6-7 fps的速度运行,这在这台计算机上增加了20%以上,表明它确实有效果。在具有更大CPU指令缓存等的计算机上,效果可能会更小,但它确实存在,因为这与FF引擎本身有关(免责声明:我并不声称这是一项科学测试,但是,只是一个指针:-))

下一个版本将这些变量缓存为对象(自身)的属性,以表明与直接使用大型全局对象相比,这也提高了性能-结果与上面的结果大致相同:

总之 根据结果和以前的经验,我确信PIXI可以更快地运行代码,因为它使用定制的小尺寸对象,而不是直接从画布和图像等大对象(元素)获取属性


在对象遍历树和分支方面,FF引擎似乎还没有V8引擎那么“聪明”,因此缓存变量确实会对FF产生影响,当需求较高时(例如每“帧”绘制16500只兔子时),FF就会显示出来。

我怀疑这是一些画布合成问题。默认情况下,画布是透明的,因此页面背景需要与画布内容相结合

我在他们的资料里找到了这个

// update the background color
if (this.view.style.backgroundColor != stage.backgroundColorString &&
    !this.transparent) {
    this.view.style.backgroundColor = stage.backgroundColorString;
}
也许他们在这个演示中将画布设置为不透明的(小提琴对我来说不太管用,似乎大多数的兔子在大多数情况下都会跳出一个非常大的dt)


我不认为这是一个对象属性访问时间/可编译性的问题:这一点是正确的,但我不认为它能解释这么大的差异。

这很有趣,在Chrome 31上,我的小提琴版本有16500只兔子,每秒15帧,Pixi版本有每秒10帧。然而,对于Firefox,Pixi更快。而且它似乎并不是说
drawImage(img,0,0)
drawImage(img,x,y)
快。我不太明白为什么人们会对这个答案投反对票。即使它不能100%回答这个问题,这也是一个有洞察力的分析-/这很有道理。你对这件事有什么意见吗
/// cache object properties
var lastTime = 0,
    w = canvas.width,
    h = canvas.height,
    iw = image.width,
    ih = image.height;
var RENDER = function () {
    this.width = canvas.width;
    this.height = canvas.height;
    this.imageWidth = image.width;
    this.imageHeight = image.height;
}
// update the background color
if (this.view.style.backgroundColor != stage.backgroundColorString &&
    !this.transparent) {
    this.view.style.backgroundColor = stage.backgroundColorString;
}