Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE9 memory leak for dynamic DOM objects with ID attribute

I've noticed that assigning the ID attribute a value to dynamically created DOM objects causes IE9 to leak memory. Has anyone else experienced this, and more importantly, know of any work-arounds? It does not leak in other browsers, even IE6 passes!

Demonstration of leak code:

It simply adds and removes rows from a table continuously and assigns an ID to each row to be used for lookup later.

No leak occurs without "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>

I noticed that removing all cells from the table row causes the memory leak to shrink, so I guess IE holds on to the row after its been removed from the table.

I also tried a work-around that added the created table rows into an Javascript object to be used as a hash-table instead of relying on getElementById(row.id) but that also leaked for some reason I cannot see.

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]; 
like image 339
Niklas Bäckman Avatar asked Feb 07 '12 12:02

Niklas Bäckman


1 Answers

I found a suitable solution in my case by noticing that reloading the included test page after it had been "running" for a while caused the memory usage to stay constant temporarily (relative to the time it had been running before reload). After that it started rising again.

So, it seems that, yes, IE does not remove the resources used by ID:d elements completely after the element is removed, but it will apparently re-use those resources if the same ID is added to the page again.

Ergo, just make sure that the IDs being added and removed are part of a limited set and not an unbounded one. The test page uses strictly increasing integer-based IDs and my original problem case used similar sequence number IDs. Luckily it's quite easy to fix them to a limited range in both cases.

For the test code above:

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

like image 66
Niklas Bäckman Avatar answered Nov 02 '22 21:11

Niklas Bäckman