【问题标题】:Memory leak in JSJS中的内存泄漏
【发布时间】:2019-03-19 13:51:32
【问题描述】:

我有一个包含以下内容的 javascript 文件。

"use strict";
$(function () {
var divs = $(".sc-frames");
var next = 0;
var currentIndex = 0;

var request = function (action, controller, div) {
    var url = "../" + controller + "/" + action;

    $.ajax({
        type: "GET",
        url: url,
        dataType: "html",
        async: false,
        timeout:10000,
        success: function (result) {

            writeResponse(result, div);
        },
        error: function () {
            $("#errorMessage").show();
        }
    });
};

var writeResponse = function (result, div) {
    $(div).hide().html(result).slideDown("slow"); 
    currentIndex = divs.index($(div));
    if (parseInt(divs.length - 1) == parseInt(currentIndex)) {
        next = 0;
    } else {
        next++;
    }
};

var createRequest = function () {
    $("#errorMessage").hide();
    $(divs[currentIndex]).empty(); 
    var div = divs[next]; 
    var action = $(div).attr("data-action");
    var controller = $(div).attr("data-controller");
    request(action, controller, div);
};

setInterval(createRequest, 30000);
createRequest(); 

});

这只是对 3 个控制器操作方法进行 ajax 调用,并将视图按顺序连续发布到 div。

但是当我在谷歌浏览器开发工具中检查性能监视器时,它显示了一个 js 内存泄漏。 Js堆大小在慢慢增加。

有没有办法找出内存泄漏的确切位置?

提前致谢。

更新

【问题讨论】:

    标签: javascript asp.net-mvc memory-leaks


    【解决方案1】:

    Js 堆大小在慢慢增加。

    这不是(必然)内存泄漏。它发生在大多数引擎使用 stop-the-world 垃圾收集时,这意味着变量将保留在内存中,尽管它们可能已经被收集,然后在某个时候 GC 启动,停止当前正在执行的 JS,检查所有引用并释放不再引用的内存,然后继续执行(这样做是因为 JS 非常动态,如果您一次检查所有变量,您无法判断离开范围的变量是否已完全取消引用您知道当然)。

    但是,这使得垃圾收集成为一项性能成本高昂的操作。因此,GC 尝试尽可能少地启动,这意味着它仅在需要内存时才启动(因为它已满)。

    因此,您不一定有内存泄漏(我在代码中没有看到)。在较长时间内观察堆,并等待几个 gc 周期或trigger them manually(当时看起来像锯子),然后检查整个图形是否在增加。如果是这样,您就会发生内存泄漏,因为有些元素在垃圾收集中幸存下来,它们正在泄漏。

    有没有办法找出内存泄漏的确切位置?

    使用大多数调试器,您可以创建当前内存状态的“快照”。取其中两个,一个在垃圾回收之前和之后,然后比较它们以找出泄漏的确切内容,然后通常可以追溯到泄漏它的代码。

    【讨论】:

    • 你是对的,当图表下降一点时,它会启动 GC。但是整体图在增加。有没有办法通过javascript清除呢?
    • @liroforum 增加了多少? gc多久启动一次?你强制 gc 了吗?
    • 我在描述部分添加了屏幕截图。我手动强制 GC,这在最后 3 次下降中显示。但总体图表有所增加。
    • @liroforum 您在很短的时间内进行测量。如果您创建一个小时左右的图表会发生什么?
    • 类似的结果。
    【解决方案2】:

    你需要使用clearInterval(createRequest);

    当您不再需要运行代码时。

    【讨论】:

      【解决方案3】:

      您可以通过删除小部分功能(或单行)来确定它何时不会发生 - 然后您就知道是什么原因造成的。但是,我找不到你停止循环的地方?也许这是每 30 秒发送一次请求并且永不停止?

      【讨论】:

      • 这是在屏幕上连续运行,所以永远不会停止。有没有办法在每个午夜清除代码中的内存?
      • 好的,刷新页面。你为什么想做这个?您可以使用 websocket 或其他技术将内容推送给您的客户。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-20
      相关资源
      最近更新 更多