6

Me he dado cuenta de que asignarle un valor al atributo de ID a los objetos DOM creados dinámicamente hace que IE9 pierda memoria. ¿Alguien más ha experimentado esto y, lo que es más importante, conoce alguna solución alternativa? No se filtra en otros navegadores, ¡incluso IE6 pasa!Fuga de memoria IE9 para objetos DOM dinámicos con el atributo de ID

Demostración de código de fugas:

Simplemente añade y elimina filas de una tabla de forma continua y asigna una identificación para cada fila que se utilizará para la búsqueda posterior.

No se produce ninguna fuga sin "row.id = eid;"

<html> 
    <head> 
     <script type="text/javascript"> 

     function addRow(tbl, index) { 
      var row = tbl.insertRow(index); 
      var eid = "loongrowid" + count; 
      row.id = eid; 

      for (var i = 0; i < 9; i++) { 
       row.insertCell(i); 
      } 

      return row; 
     } 

     function removeTableRow(tbl, index) { 
      var row = tbl.rows[index]; 
      tbl.deleteRow(index); 

     } 

     var count = 1; 

     function fillRow(row){ 
      row.cells[0].innerHTML = '<input type="checkbox"' + ' checked="checked"' + ' />'; 
      for (var i = 1; i < 9; i++) { 
       row.cells[i].innerHTML = count + " c"; 
      } 
      ++count; 
     } 

     var added = false; 

     function dostuff() 
     { 
      var tbl = document.getElementById("tbl"); 
      var i; 

      if (added) 
      { 
       for (i = 0; i < 20; ++i) 
       { 
        removeTableRow(tbl,1); 
       } 
      } 
      else 
      { 
       for (i = 0; i < 20; ++i) 
       { 
        var row = addRow(tbl, i+1); 
        fillRow(row); 
       } 
      } 

      added = !added; 
      setTimeout(dostuff, 1); 
     } 
     </script> 
    </head> 
    <body onload="setTimeout(dostuff, 1)"> 
    <h1 id="count">TESTING</h1> 
    <table id="tbl" style="width:100%;">  
    <tr> 
     <th>selected</th> 
     <th>date</th> 
     <th>time</th> 
     <th>place</th> 
     <th>device</th> 
     <th>text</th> 
     <th>state</th>   
     <th>status</th> 
     <th>quality</th> 
    </tr> 
    </table> 
    </body> 
</html> 

me di cuenta de que la eliminación de todas las celdas de la fila de la tabla hace que la pérdida de memoria a contraerse, así que supongo que IE se aferra a la fila después de su sido retirado de la mesa.

También probé una solución temporal que agregaba las filas de la tabla creada en un objeto Javascript para usar como tabla hash en lugar de confiar en getElementById (row.id) pero que también se filtró por algún motivo que no puedo ver.

var hash = []; 

    // when creating row 
    row.extid = eid; // Note: this by itself causes no leak 
hash[eid] = row; 

    // when removing row 
delete hash[row.extid]; 
+0

¿Intentó asignar la identificación con 'setAttribute'? En teoría, no debería hacer ninguna diferencia, pero nunca sabemos ... – bfavaretto

+0

Lo intenté, pero no hizo ninguna diferencia. –

+0

¿Hay algún problema en el funcionamiento lento de este código o en el IE que consume demasiada memoria? ¿Intentó insertar en DOM una vez, primero recopilando todo el HTML nuevo en alguna variable? – shershen

Respuesta

2

Encontré una solución adecuada en mi caso al notar que volver a cargar la página de prueba incluida después de haber estado "funcionando" durante un tiempo causaba que el uso de la memoria permaneciera constante temporalmente (en relación con el tiempo que estuvo funcionando antes de volver a cargar). Después de eso comenzó a subir de nuevo.

Parece que sí, IE no elimina completamente los recursos utilizados por los elementos ID: d después de eliminar el elemento, pero aparentemente volverá a utilizar esos recursos si se vuelve a agregar la misma ID a la página .

Ergo, solo asegúrese de que las ID que se agregan y quitan son parte de un conjunto limitado y no ilimitado. La página de prueba utiliza identificaciones basadas en números enteros estrictamente crecientes y mi caso problema original usa IDs de número de secuencia similares. Afortunadamente, es bastante fácil arreglarlos en un rango limitado en ambos casos.

Para el código de prueba anterior:

++ count; if (count> 1000) count = 0;

0

En mis días de Java Swing (sí, sí, estoy de edad), la JVM tenían un problema algo similar. En este sentido, el recolector de basura no podría limpiar los objetos Swing que estaban anidados dentro de otros objetos Swing y causar una pérdida de memoria.

Solía ​​solucionar esto estableciendo explícitamente cada objeto Swing en NULL, ya que ya no eran necesarios.

En el caso de objetos profundamente anidados (es decir, tablas Swing que contienen otros objetos Swing), escribí un método recursivo que podría ser utilizado por todas mis clases Swing que atravesaría cualquier objeto Swing, NULL-ing cada objeto encontrado dentro.

Fue irritante que tuve que hacer todo este esfuerzo extra solo para solucionar un error en el recolector de basura de la JVM, pero funcionó muy bien. Una vez que tuve esto en su lugar, las pérdidas de memoria desaparecieron.

Puede valer la pena el experimento de intentar algo similar con IE9. Obligar a los objetos DOM a NULL, ya que ya no son necesarios, puede resolver esto por usted. Y el resto de nosotros también ... :-)

+0

Probé los consejos documentados aquí (http://toranbillups.com/blog/archive)/2009/04/21/Cleanup-for-dynamically-generated-DOM-elements-in-IE), pero fue en vano. También escuché a otros decir que, en realidad, IE9 SOLUCIONA los problemas de pérdida de memoria en versiones anteriores de IE, por lo que tal vez se trate de una nueva pérdida exclusiva de IE9. Nueva base de código, supongo. –