<div dir="ltr">Hi,<div><br></div><div>Did anyone had the opportunity to look into this bug report and in the proposed fix?<br></div><div><br></div><div>Sincerely,</div><div>Saulo</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 12, 2016 at 10:55 PM, Saulo Araujo <span dir="ltr"><<a href="mailto:saulo2@gmail.com" target="_blank">saulo2@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi,</div><div><br></div><div>I believe there is a substantial memory leak in the JavaScript runtime of Ur/Web. To see it happening:</div><div><br></div><div>1) visit <a href="http://timesheet-ur.sauloaraujo.com:8080/TimeSheet/application" target="_blank">http://timesheet-ur.<wbr>sauloaraujo.com:8080/<wbr>TimeSheet/application</a> with Google Chrome</div><div>2) open the developer tools by pressing f12</div><div>3) click in the "Profiles" tab</div><div>4) click in the "Take Heap Snapshot" radio button</div><div>5) click in the "Take Snapshot" button</div><div>6) type Detached in the "Class filter" text box (you will see that the heap has about 7MB and Detached DOM trees are retaining 0% of the memory - <a href="https://snag.gy/2nF9fz.jpg" target="_blank">https://snag.gy/2nF9fz.jpg</a>)</div><div><br></div><div>7) click 10 times in the foward icon (the one on the right of the "Date" header in the time sheet application)</div><div>9) click in the "Take Snapshot" button</div><div>10) type Detached in the "Class filter" text box (you will see that the heap has about 43MB and Detached DOM trees are retaining 16% of the memory - <a href="https://snag.gy/Crc3Vg.jpg" target="_blank">https://snag.gy/Crc3Vg.jpg</a>)</div><div><br></div><div>11) click 10 times in the foward icon (the one on the right of the "Date" header in the time sheet application)</div><div>12) click in the "Take Snapshot" button</div><div>13) type Detached in the "Class filter" text box (you will see that the heap has about 78MB and Detached DOM trees are retaining 17% of the memory - <a href="https://snag.gy/P5BLhq.jpg" target="_blank">https://snag.gy/P5BLhq.jpg</a>)</div><div><br></div><div>I have spent quite some time investigating this memory leak and I believe the problem is in the function recreate inside the function dyn:</div><div><br></div><div>function dyn(pnode, s) {</div><div>    if (suspendScripts)</div><div>        return;</div><div><br></div><div>    var x = document.createElement("<wbr>script");</div><div>    x.dead = false;</div><div>    x.signal = s;</div><div>    x.sources = null;</div><div>    x.closures = null;</div><div><br></div><div>    var firstChild = null;</div><div><br></div><div>    x.recreate = function(v) {</div><div>        for (var ls = x.closures; ls; ls = ls.next)</div><div>            freeClosure(ls.data);</div><div><br></div><div>        var next;</div><div>        for (var child = firstChild; child && child != x; child = next) {</div><div>            next = child.nextSibling;</div><div><br></div><div>            killScript(child);</div><div>            if (child.getElementsByTagName) {</div><div>                var arr = child.getElementsByTagName("<wbr>script");</div><div>                for (var i = 0; i < arr.length; ++i)</div><div>                    killScript(arr[i]);</div><div>            }</div><div>...</div><div><br></div><div>Note that recreate only kills <script> nodes . Therefore, <input>, <textarea> and <select> nodes created through <ctextbox>, <ctextarea> and <cselect> will continue to be in the dyns lists of its sources. To fix this memory leak, I propose changing the function dyn to</div><div><br></div><div>function dyn(pnode, s) {</div><div>    if (suspendScripts)</div><div>        return;</div><div><br></div><div>    var x = document.createElement("<wbr>script");</div><div>    x.dead = false;</div><div>    x.signal = s;</div><div>    x.sources = null;</div><div>    x.closures = null;</div><div><br></div><div>    var firstChild = null;</div><div><br></div><div>    x.recreate = function(v) {</div><div>        for (var ls = x.closures; ls; ls = ls.next)</div><div>            freeClosure(ls.data);</div><div><br></div><div>        var next;</div><div>        for (var child = firstChild; child && child != x; child = next) {</div><div>            next = child.nextSibling;</div><div><br></div><div>            killDyns(child)</div><div>...</div><div><br></div><div>Below is the function killDyns.</div><div><br></div><div>function killDyns(node) {</div><div>    var nodeIterator = document.createNodeIterator(<wbr>node, NodeFilter.SHOW_ELEMENT, function (node) {</div><div>        return node.dead !== undefined && node.dead === false</div><div>    })</div><div>    var node = nodeIterator.nextNode();</div><div>    while (node) {</div><div>        killScript(node);</div><div>        node = nodeIterator.nextNode();</div><div>    }</div><div>}</div><div><br></div><div>killDyns traverses all descendants of a node that have a dead attribute equal to false and kills them with killScript. Therefore, killDyns may be less performant than the code it substitutes, but I believe killDyns is less prone to memory leaks than the original code. There is another small change to be done in urweb.js. You can see all changes in <a href="https://github.com/saulo2/urweb/commit/dcd280c85595ceee60a4fb78a3bfaf413a9eb7b8#diff-867e8dfbbc36419eefc0dfdf9db32883" target="_blank">https://github.com/saulo2/<wbr>urweb/commit/<wbr>dcd280c85595ceee60a4fb78a3bfaf<wbr>413a9eb7b8#diff-<wbr>867e8dfbbc36419eefc0dfdf9db328<wbr>83</a></div><div><br></div><div>I did not make a pull request yet because I would like to know the opinion of the Ur/Web comitters about this fix. Maybe there is something that can be improved. Maybe there is a new bug in it :) In any case, repeating the previous steps with the proposed changes, I get the following results:</div><div><br></div><div>6) type Detached in the "Class filter" text box (you will see that the heap has about 7MB and Detached DOM trees are retaining 0% of the memory - <a href="https://snag.gy/NicJow.jpg" target="_blank">https://snag.gy/NicJow.jpg</a>)</div><div>10) type Detached in the "Class filter" text box (you will see that the heap has about 15MB and Detached DOM trees are retaining 0% of the memory - <a href="https://snag.gy/nuVfhg.jpg" target="_blank">https://snag.gy/nuVfhg.jpg</a>)</div><div>13) type Detached in the "Class filter" text box (you will see that the heap has about 21MB and Detached DOM trees are retaining 0% of the memory - <a href="https://snag.gy/aPeUuK.jpg" target="_blank">https://snag.gy/aPeUuK.jpg</a>)</div><div><br></div><div>The new results suggest that there is another memory leak in the JavaScript Runtime. However, I have not looked into it yet.</div><div><br></div><div>Sincerely,</div><div>Saulo</div></div>
</blockquote></div><br></div>