JavaScript 中的性能内存管理

Posted

技术标签:

【中文标题】JavaScript 中的性能内存管理【英文标题】:Performance Memory Management in JavaScript 【发布时间】:2012-04-20 20:55:55 【问题描述】:

让我从问题开始,然后填写原因/背景。

问题:有没有针对 javascript 的内存分析工具?

问题:有人已经在 J​​avaScript 中测试过性能内存管理吗?

我想在 JavaScript 中试验性能内存管理。在 C/C++/Assembly 中,我能够在一个巨大的块中分配一个内存区域,然后将我的数据结构映射到该区域。这有几个性能优势,尤其是对于数学繁重的应用程序。

我知道我无法在 JavaScript(或 Java)中分配内存和映射我自己的数据结构。但是,我可以使用一些预定数量的对象(例如 Vector 对象)创建堆栈/队列/堆。在处理数字时,我经常在任何时候都只需要几个这样的对象,但随着时间的推移会产生大量的数字。通过重用旧的向量对象,我可以避免创建/删除时间、不必要的垃圾收集时间以及等待垃圾收集时潜在的大内存占用。我还假设它们都将在内存中保持相当接近,因为它们是同时创建的并且经常被访问。

我想对此进行测试,但我缺少内存分析工具。我试过 FireBug,但它没有告诉你 JavaScript 引擎当前分配了多少内存。

我能够编写一个简单的 CPU 性能测试代码(见下文)。我将一个包含 10 个“矢量”对象的队列与每次使用 new/delete 进行了比较。为了确定我不只是使用空数据,我分配了 Vector 6 个浮点属性、一个三值数组(浮点数)和一个 18 个字符的字符串。每次我使用任何一种方法创建一个向量时,我都会将所有值设置为 0.0。

结果令人鼓舞。显式管理方法最初更快,但 javascript 引擎有一些缓存,并且在运行几次测试后就赶上了。最有趣的部分是,当我尝试在 1000 万个对象上运行标准的 new/delete 时,FireBug 崩溃了,但对于我的队列方法来说工作得很好。

如果我能找到内存分析工具,我想在不同的结构(数组、堆、队列、堆栈)上进行测试。我还想在一个真实的应用程序上测试它,也许是一个超级简单的光线追踪器(快速编码,可以测试非常大的数据集,其中包含大量数学以进行良好的分析)。

是的,我在创建这个问题之前进行了搜索。我发现的所有内容要么是关于 JavaScript 内存泄漏的讨论,要么是关于 GC 与显式管理的讨论。

谢谢, JB

标准方法

function setBaseVectorValues(vector) 
    vector.x = 0.0;
    vector.y = 0.0;
    vector.z = 0.0;
    vector.theta = 0.0;
    vector.phi = 0.0;
    vector.magnitude = 0.0;
    vector.color = [0.0, 0.0, 0.0];
    vector.description = "a blank base vector";


function standardCreateObject() 
    var vector = new Object();
    setBaseVectorValues(vector);

    return vector;


function standardDeleteObject(obj) 
    delete obj;


function testStandardMM(count) 
    var start = new Date().getTime();
    for(i=0; i<count; i++) 
        obj = standardCreateObject();
        standardDeleteObject(obj);
    
    var end = new Date().getTime();

    return "Time: " + (end - start)

托管方法

我使用了来自http://code.stephenmorley.org/javascript/queues/的JavaScript队列

function newCreateObject() 
    var vector = allocateVector();
    setBaseVectorValues(vector);

    return vector;


function newDeleteObject(obj) 
    queue.enqueue(obj);


function newInitObjects(bufferSize) 
    queue = new Queue()
    for(i=0; i<bufferSize; i++) 
        queue.enqueue(standardCreateObject());
    


function allocateVector() 
    var vector
    if(queue.isEmpty()) 
        vector = new Object();
    else 
        vector = queue.dequeue();
    

    return vector;


function testNewMM(count) 
    start = new Date().getTime();
    newInitObjects(10);
    for(i=0; i<count; i++) 
        obj = newCreateObject();
        newDeleteObject(obj);
        obj = null;
    
    end = new Date().getTime();

    return "Time: " + (end - start) + "Vectors Available: " + queue.getLength();

【问题讨论】:

由于这个问题涉及一些背景研究,所以我将只支持这个答案。 【参考方案1】:

chrome 检查器有一个不错的 javascript 分析工具。我会试试...

【讨论】:

提示:尽量少使用匿名函数。在浏览分析数据时提供帮助。 是的,我喜欢 Chrome 检查器。但是,它实际上只能很好地描述时间。 @James,Chrome 有两个很好的内存分析工具...看看“时间轴”选项卡(选择“内存”,然后点击底部的记录按钮)和“配置文件”选项卡(选择“Take Heap Snapshot”然后开始)。【参考方案2】:

我从未见过这样的工具,但实际上,javascript [几乎] 从未独立运行;它[几乎]总是托管在另一个应用程序中(例如您的浏览器)。与您的特定数据结构关联多少内存并不重要,重要的是主机应用程序的整体内存消耗如何受脚本影响。

我建议为您的操作系统找到一个通用的内存分析工具并将其指向您的浏览器。运行单个页面并分析浏览器在触发代码之前和之后的内存消耗变化。

我现在能想到的唯一例外是node.js...如果您使用的是node,那么您可以使用process.memoryUsage()

编辑: 哦……经过一番搜索,似乎Chrome has some sweet tools 也是如此。 (+1 for Michael Berkompas)。我仍然坚持我最初的说法,实际上更重要的是查看浏览器进程本身的内存使用情况如何受到影响,但 Chrome 工具的优雅令人印象深刻。

【讨论】:

我曾想过分析整个应用程序,但希望不会这样。我喜欢使用 node.js 中的 process.memoryUsage() 的想法。 这可能很明显,但每个 javascript 引擎都会显示不同的结果。 Node.js 使用 V8(与 Chrome 相同的引擎),但 Firefox、Safari 和 IE 都将使用不同的 js 引擎。如果您想要真实世界的结果,那么真实世界的条件是最好的测试方法。祝你好运!

以上是关于JavaScript 中的性能内存管理的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript性能优化1——内存管理(JS垃圾回收机制引用计数标记清除标记整理)

JavaScript性能优化1——内存管理(JS垃圾回收机制引用计数标记清除标记整理V8分代回收Performance使用)

JavaScript 性能优化

javascript的垃圾收集机制

27 JavaScript数据类型与内存管理

JavaScript内存管理闭包和内存泄漏