Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.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 Chrome下web应用程序中的巨大节点泄漏-开发者工具未报告原因_Javascript_Google Chrome_Web Applications_Memory Leaks_Nodes - Fatal编程技术网

Javascript Chrome下web应用程序中的巨大节点泄漏-开发者工具未报告原因

Javascript Chrome下web应用程序中的巨大节点泄漏-开发者工具未报告原因,javascript,google-chrome,web-applications,memory-leaks,nodes,Javascript,Google Chrome,Web Applications,Memory Leaks,Nodes,我有一个相当复杂的web应用程序,它以难以置信的速度泄漏节点。使用windows任务管理器,我可以看到chrome进程使用的内存量每秒增加约3MB 我最初的方法是禁用部分应用程序,以隔离导致问题的区域。经过一点尝试和错误发现,原因是文档中的一些表更新。该应用程序每秒从服务器请求数据,以更新多个数据表。每个表都以相同的方式更新。将从表中删除所有行,并插入包含更新数据的新行。在检查执行此操作的通用代码时,我看不到问题 为了解决这个问题,我显然转向了Chrome开发工具。我的问题是,这些工具给我的信息

我有一个相当复杂的web应用程序,它以难以置信的速度泄漏节点。使用windows任务管理器,我可以看到chrome进程使用的内存量每秒增加约3MB

我最初的方法是禁用部分应用程序,以隔离导致问题的区域。经过一点尝试和错误发现,原因是文档中的一些表更新。该应用程序每秒从服务器请求数据,以更新多个数据表。每个表都以相同的方式更新。将从表中删除所有行,并插入包含更新数据的新行。在检查执行此操作的通用代码时,我看不到问题

为了解决这个问题,我显然转向了Chrome开发工具。我的问题是,这些工具给我的信息相互矛盾

  • 时间线工具显示节点数量每秒增加约28000个。强制垃圾收集不会将其还原到原始级别
  • Timeline工具显示JS堆大小随时间变化。强制垃圾收集将堆返回到其原始大小(加上或减去几个100K)
  • 使用“三个快照”技术,探查器堆快照工具不会显示快照3中存在的快照1和快照2之间创建的HTML或文本节点
  • 比较快照显示了许多HTMLTableRowElement、HTMLTableCellElement、HTMLInputElement和Text节点的创建和删除。未报告节点计数增加
  • 探查器-堆分配工具验证堆快照工具的结果。在任何点都没有任何节点类型的泄漏报告
  • 堆工具显示(编译代码)、(数组)和(系统)类型略有增加
  • 堆配置文件工具报告,对于我的“原始”javascript版本的应用程序,堆大小约为12MB,对于我的闭包编译器编译版本的应用程序,堆大小约为7MB。随着时间的推移,这些值不会增长太多
  • 这让我有点困惑。显然是内存泄漏。Windows任务管理器和时间线工具将其报告为节点泄漏,但堆分析工具和JS堆时间线未显示该问题

    据我所知,HTMLTableRowElements只在两个地方被引用,文档中和用于按值查找的对象中。清除表格时,对象始终被清除。我可以通过更改代码来创建所有节点来“解决”这个问题,但决不将它们插入文档,只在对象中引用它们。显然,这不是一个修复,因为用户看不到数据

    经过两天的测试和调查,我现在不知道如何继续。如果你加入IE和Firefox,情节会变得更加复杂。这些浏览器似乎没有相同的内存/节点泄漏。我也相信Chrome以前不存在这个问题。不幸的是,似乎没有办法回到以前的chrome版本,看看它是否是chrome中的一个bug

    有人对此有什么建议吗。我是否遗漏了一些东西,或者误解了开发人员工具的输出?有没有办法回到以前的chrome版本?这听起来像Chrome中的bug吗?欢迎大家发表意见

    这是使用Google的Closure API插入项目的代码:

    /**
     * Inserts and/or updates a row in the table.
     * 
     * @param {string|number} rowId The identifier of the row in the rows_ map
     * @param {boolean} insertTop If true the row is inserted at the top of the document
     * @param {...goog.dom.Appendable} var_args The items to add to each cell in the row
     */
    sm.ui.DataTable.prototype.updateRow = function(rowId, insertTop, var_args) {
        var dom = this.getDomHelper();
    
        // Insert the new session data
        if(!this.rows_[rowId]) {
            // There is no row present (simple case of create one)
    
            // Create the table row
            var row = this.rows_[rowId] = dom.createDom('tr', {'style' : 'display: none;'});
    
            var colView = this.colView_;
            var colNames = this.columnNames_;
    
            for(var i = 0; i < colNames.length; i++) {
                var cell = dom.createDom('td');
                if(!colView[i]) {
                    goog.style.showElement(cell, false);
                }
                row.appendChild(cell);
            }
    
            // Add to the table if element exists
            var element = this.getElement();
            var tBody = element.tBodies[0];
            if(element) {
                this.showPage_(this.currentPage_, false);
                if(insertTop) {
                    // Insert a row at the top of the table
                    tBody.insertBefore(row, tBody.rows[0] || null);
                } else {
                    // Append to the end if insert top no set true
                    tBody.appendChild(row);
                }
                this.showPage_(this.currentPage_, true);
    
                // Update the footer to as it may need displaying or changing
                this.updateFooter_();   
            }
        }
    
        // Loop over the var args and set the content of each cell
        // arguments will be string, Node, array of strings and Nodes
        for (var i = 0; i < arguments.length - 2; i++) {
            var row = this.rows_[rowId];
    
            dom.removeChildren(row.cells[i]);           
            dom.append(row.cells[i], arguments[i + 2]); // Removing this line "cures" the problem.
        }
    };
    
    /**
     * Removes all rows from the table.
     * @param {string=} opt_message Message to display in the instead of data (reset table again to clear)
     */
    sm.ui.DataTable.prototype.reset = function (opt_message) {
    
        var element = this.getElement();
        var tBody = element.tBodies[0];
        while(tBody.rows.length > 0) {
            tBody.deleteRow(0);
        }
    
        // Reset the rows and pages
        this.rows_ = {};
        this.currentPage_ = 1;
    
        this.updateFooter_();
    
        if(opt_message) {
            // Create the row to inset in the table
            // Ensure it spans all the columns
            var dom = this.getDomHelper();
            var messageCell = dom.createDom('tr', null, 
                dom.createDom('td', {'colspan' : this.columnNames_.length}, opt_message));
            goog.dom.append(tBody,messageCell);
        }
    };
    
    /**
    *在表中插入和/或更新行。
    * 
    *@param{string | number}rowId行映射中行的标识符
    *@param{boolean}insertTop如果为true,则在文档顶部插入行
    *@param{…goog.dom.Appendable}var_指定要添加到行中每个单元格中的项
    */
    sm.ui.DataTable.prototype.updateRow=函数(rowId、insertTop、var_args){
    var dom=this.getDomHelper();
    //插入新的会话数据
    如果(!this.rows_u[rowId]){
    //没有行(创建一行的简单情况)
    //创建表行
    var row=this.rows.[rowId]=dom.createDom('tr',{'style':'display:none;'});
    var colView=this.colView;
    var colNames=this.columnNames\ux;
    对于(var i=0;i0){
    tBody.deleteRow(0);
    }
    //重置行和页
    this.rows{};
    此.currentPage u=1;
    this.updateFooter(();
    如果(选择信息){
    //创建行
    
    function walkTheDOM(node, func)
    {
      func(node);
      node = node.firstChild;
      while (node)
      {
        walkTheDOM(node, func);
        node = node.nextSibling;
      }
    }
    
    function purgeEventHandlers(node)
    {
      walkTheDOM(node, function (n) {
        var f;
    
        for (f in n)
        {
          if (typeof n[f] === "function")
          {
            n[f] = null;
          }
        }
      });
    }
    
    // now you can remove the node from the DOM