Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/78.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 Webworker画布性能糟糕_Javascript_Html_Canvas_Web Worker_Fractals - Fatal编程技术网

Javascript Webworker画布性能糟糕

Javascript Webworker画布性能糟糕,javascript,html,canvas,web-worker,fractals,Javascript,Html,Canvas,Web Worker,Fractals,我正在尝试使用webworkers为动画mandelbrot缩放器渲染部分帧,因为其中涉及大量计算,并且可以很容易地划分为块,这应该是并行处理的理想情况 但是,无论我做什么尝试,我都不会因为工人们使用的额外cpu而获得任何性能回报。与非工作版本相比,在Chrome中我的基准测试稍微慢一些,在Firefox中则慢得多 我的猜测是,将图像数据传输到webworkers非常昂贵,我尝试只接收原始数据并使用它渲染帧,但结果基本相同。我不认为这是向workers发送和接收imagedata的理想方式(事实

我正在尝试使用webworkers为动画mandelbrot缩放器渲染部分帧,因为其中涉及大量计算,并且可以很容易地划分为块,这应该是并行处理的理想情况

但是,无论我做什么尝试,我都不会因为工人们使用的额外cpu而获得任何性能回报。与非工作版本相比,在Chrome中我的基准测试稍微慢一些,在Firefox中则慢得多

我的猜测是,将图像数据传输到webworkers非常昂贵,我尝试只接收原始数据并使用它渲染帧,但结果基本相同。我不认为这是向workers发送和接收imagedata的理想方式(事实上,我只需要接收它,但我无法在workers内部创建一个可以直接用于画布的缓冲区)。因此,发送任何大量数据都会造成真正的瓶颈

亲爱的stackoverflow,请帮我回答这两个问题:我在这里做错了什么,还有什么可以改进的

可以找到工人的演示,也可以在上找到非工人版本以供参考

代码如下:

"use strict";

/*global $*/

$(function() {

    var mandelbrot = new Mandelbrot();

});

var Mandelbrot = function() {

    // set some values
    this.width = 500;
    this.height = 500;

    this.x_center = -1.407566731001088;
    this.y_center = 2.741525895538953e-10;

    this.iterations = 250;
    this.escape = 4,
    this.zoom = 10;
    this.count = 0;
    this.worker_size = 10;
    this.received = 0;
    this.refresh = true;

    //let's go - create canvas, image data and workers
    this.init();
    //start animation loop
    this.animate();

};

Mandelbrot.prototype = {

    init: function() {

        var self = this;

        //create main canvas and append it to div
        var container = $("#content");

        this.canvas = document.createElement("canvas");
        this.canvas.width = this.width;
        this.canvas.height = this.height;

        container.append(this.canvas);

        //create imagedata
        this.context = this.canvas.getContext("2d");
        this.image = this.context.getImageData(0, 0, this.width, this.height);
        this.data = new Int32Array(this.image.data.buffer);

        //create imagedata for webworkers
        this.worker_data = this.context.getImageData(0, 0, this.width, this.height / this.worker_size);

        //create webworkers drop them in array
        this.pool = [];

        for (var i = 0; i < this.worker_size; i++) {

            this.pool[i] = new Worker("js/worker.js");
            this.pool[i].idle = true;
            this.pool[i].id = i;

            //on webworker finished 
            this.pool[i].onmessage = function(e) {

                self.context.putImageData(e.data, 0, self.height / self.worker_size * e.target.id);
                self.received++;

            };

        }
    },

    iterate: function() {

        for (var i = 0; i < this.pool.length; i++) {

            this.pool[i].postMessage({

                image: this.worker_data,
                id: this.pool[i].id,
                worker_size: this.worker_size,
                width: this.width,
                height: this.height,
                x_center: this.x_center,
                y_center: this.y_center,
                iterations: this.iterations,
                escape: this.escape,
                zoom: this.zoom

            });
        }
    },

    animate: function() {

        requestAnimationFrame(this.animate.bind(this));

        //poor man's benchmark over 250 frames
        if (this.count === 0) {
            console.time("timer");
        } 

        if (this.count === 250) {
            console.timeEnd("timer");
        }

        //refresh at init, then refresh when all webworkers are done and reset
        if (this.received === this.worker_size | this.refresh) {

            this.received = 0;
            this.refresh = false;
            this.count++;
            this.zoom *= 0.95;
            this.iterate();

        }
    }
};
“严格使用”;
/*全球的$*/
$(函数(){
var mandelbrot=新的mandelbrot();
});
var Mandelbrot=函数(){
//设定一些值
这个宽度=500;
这个高度=500;
该中心=-1.407566731001088;
该中心=2.741525895538953e-10;
这个迭代次数=250次;
这个。逃逸=4,
这个.zoom=10;
此值为0.count;
此.worker_size=10;
此值=0;
this.refresh=true;
//让我们开始-创建画布、图像数据和工作人员
this.init();
//开始动画循环
这个。动画();
};
Mandelbrot.prototype={
init:function(){
var self=这个;
//创建主画布并将其附加到div
var容器=$(“#内容”);
this.canvas=document.createElement(“canvas”);
this.canvas.width=this.width;
this.canvas.height=this.height;
container.append(this.canvas);
//创建图像数据
this.context=this.canvas.getContext(“2d”);
this.image=this.context.getImageData(0,0,this.width,this.height);
this.data=新的Int32Array(this.image.data.buffer);
//为webworkers创建imagedata
this.worker_data=this.context.getImageData(0,0,this.width,this.height/this.worker_size);
//创建webworkers将它们放入数组中
this.pool=[];
对于(var i=0;i
和worker.js:

self.onmessage = function(e) {

    "use strict";

    var x_step = e.data.zoom / e.data.width;
    var y_step = e.data.zoom / e.data.height;

    var y_start = e.data.height / e.data.worker_size * e.data.id;
    var y_end = e.data.height / e.data.worker_size;

    var data = new Int32Array(e.data.image.data.buffer);

    for (var y = 0; y < y_end; y++) {

        var iy = e.data.y_center - e.data.zoom / 2 + (y + y_start) * y_step;

        for (var x = 0; x < e.data.width; x++) {

            var rx = e.data.x_center - e.data.zoom / 2 + x * x_step;

            var zx = rx;
            var zy = iy;
            var zx2 = 0;
            var zy2 = 0;

            for (var i = 0; zx2 + zy2 < e.data.escape && i < e.data.iterations; ++i) {

                zx2 = zx * zx;
                zy2 = zy * zy;
                zy = (zx + zx) * zy + iy;
                zx = zx2 - zy2 + rx;
            }

            data[y * e.data.width + x] = (255 << 24) | (i << 16) | (i << 8) | i;

        }
    }

    self.postMessage(e.data.image);

};
self.onmessage=函数(e){
“严格使用”;
var x_step=e.data.zoom/e.data.width;
var y_step=e.data.zoom/e.data.height;
变量y_start=e.data.height/e.data.worker_size*e.data.id;
变量y_end=e.data.height/e.data.worker_size;
var data=新的Int32Array(例如data.image.data.buffer);
对于(变量y=0;ydata[y*e.data.width+x]=(255我实际上在这个实验中尝试了同样的方法,这是一个位移过滤器:

我在过滤器中创建了一个worker,在将它们发布回主应用程序之前,我一起计算像素。基本上迭代worker中的所有像素

在worker之前,我有一个循环4 getImageData,这不能在worker中完成。在chrome上,不管怎样,它都需要大约15%的CPU

所以,总的来说,我在没有工人的情况下得到70%的CPU,在工人的情况下得到90%的CPU

我假设无法在worker中执行的操作,例如“getImageData”和“putImageData”,加上拥有worker本身的事实,比没有worker需要更多的CPU

如果我们能够发送其他类型的数据,这样我们就可以在worker中执行getImageData和putImageData,这可能会更好

不确定是否有其他方法发送和发送r