如何处理循环中的变量来自函数和函数的垃圾收集器?

时间:2014-12-27 03:31:56

标签: javascript performance canvas garbage-collection

我正在尝试创建我的小粒子系统作为自学,以了解有关javascript的更多信息。虽然我不是一个完整的编程初学者,但我不是专业程序员。目前我正在努力提高我对纯javascript的知识(因此我的代码中没有库)。

在阅读谷歌和其他许多人的文章后,我发现自己因垃圾收集而感到困惑。根据文章,与我的程序相比,内存图表应该看起来更平滑,并且通常也不应该调用GC。以下是google chromes开发者工具截图的链接。

有两件事我想问你,我很感激你的任何见解。

a /这种行为可能是调用var for inside函数进行循环索引的结果吗?

示例:

function doSomething(args) {
for (var i = 0; i < arr.length; i++) {/*some code*/}
}

我的动画循环经常调用不同的函数(requestanimationframe)。你如何处理循环使用的这些变量(var i)? 将它们声明为全局变量?但是,如果从不同的函数调用中获得嵌套循环,则会非常难看。

b /为变量分配函数会影响内存堆叠(在运行时创建新函数)吗?

在一篇文章中,我发现将函数赋值给变量会阻止在每个函数调用中创建新函数。 我尝试将所有函数分配给变量并以这种方式调用它们,但遗憾的是它没有改变任何东西(性能,内存图表)。

我的整个当前小粒子系统的小提琴(下面的linke)有一个测试场景。屏幕上有大约8700个粒子,我的超级慢处理器以恒定的32 fps运行。 使用四核处理器,我可以获得54-60 fps,具体取决于设置(如果我不将静止对象绘制为生成器,吸引器等,则为60 fps)。

但是当我运行它时,我会定期得到轻微的波动,所以我想对我的代码更有效并调整它。但我找到的方法并不适用于我。幸运的是,从一开始我就回收了粒子对象,所以在获得上面提到的8700粒子后,我几乎不会用新的构造函数创建任何新对象。

所以我想请你的意见。

非常感谢你阅读这篇文章: - )。

其他链接:

小提琴:http://jsfiddle.net/kwgp7kmh/1/

chrome dev工具的内存图表:http://postimg.org/image/wl7pm4zzp/

1 个答案:

答案 0 :(得分:0)

每当遇到表演的某些问题时,请使用剖析器 在这里,我看到使用32%的CPU,应该归咎于action() 行为准则过于通用,但有3个独立的案例,这使得难以阅读并降低其性能。通过更清楚地写它,我从32%CPU到3%CPU !!!!

// execute an action
// list: generate, attract, draw
function action(actions, arr, addParticles, arg2) {
    if (actions == 'draw') {
        for (var i = 0; i < arr.length; i++) {
            arr[i].draw();
        }
        return;
    } else if ('generate' in actions) {
        if (addParticles) {                
            var generators = actions['generate'];
            for (var i = 0; i < generators.length; i++) {
                 generators[i].generate(arr);
            }
        }
    }
    var attractors = actions['attract'];
    if (attractors) {
        for (var j = 0; j < attractors.length; j++) {
            for (var i = 0; i < data.lives; i++) {
                attractors[j].attract(arr[i]);
            }
        }
    }
    var repulsors = actions['repulse'];
    if (repulsors) {
        for (var j = 0; j < repulsors.length; j++) {
            for (var i = 0; i < data.lives; i++) {
                repulsors[j].repulse(arr[i], arg2);
            }
        }
    }
}

移动可以通过一点点简单的缓存获得一点点。

粒子的绘制是在更新中完成的(已修复)+其他一些修复使您的应用更加流畅:

http://jsfiddle.net/gamealchemist/kwgp7kmh/3/

编辑:
上面的代码更快,因为它将由Javascript引擎编译,它将假设(这是正确的)每个数组只包含相同类型的对象。因此,成本将更接近相同C ++代码的成本 另一方面,写作时:

 actions[prop][j][prop](arr[i], arg1, arg2); 

每次引擎执行所有操作时:阅读propactions,检索prop[actions](1),检索其j - 元素(2),检索这个元素(3)的prop方法,检索arr [i](4);然后打电话,4个昂贵的操作,不能使用类型假设进行优化。你必须编写一个相当明显的代码&#39;使发动机能够优化它。