jQuery UI Widgets Forums Grid Memory leak using jqxgrid in an iframe

This topic contains 16 replies, has 7 voices, and was last updated by  dhroth 2 years, 8 months ago.

Viewing 15 posts - 1 through 15 (of 17 total)
  • Author

  • francois
    Participant

    Hello,

    I have noticed a very important memory leak when using jqxGrid inside an iframe. Every time the iframe has to reload (which is my context can be often), every script is recompiled but the old versions are not garbage collected.

    Here is how to reproduce this issue:

    iframe.html:

    <html> 
    <head> 
    </head> 
    <body>
    <iframe src="grid.html" width="100%" height="100%"></iframe> 
    </body> 
    </html>

    grid.html:

    
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/HTML; charset=utf-8" />
    <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="https://jqwidgets.com/public/jqwidgets/jqx-all.js"></script>
    <link rel="stylesheet" type="text/css" href="https://jqwidgets.com/public/jqwidgets/styles/jqx.base.css">
    <link rel="stylesheet" type="text/css" href="https://jqwidgets.com/public/jqwidgets/styles/jqx.energyblue.css">
    <script type="text/javascript" src="https://jqwidgets.com/jquery-widgets-demo/demos/jqxgrid/generatedata.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
     var data = generatedata(500);
     var source = {
       localdata: data,
       datafields: [{
           name: 'firstname',
           type: 'string'
       }, {
           name: 'lastname',
           type: 'string'
       }, {
           name: 'productname',
           type: 'string'
       }, {
           name: 'date',
           type: 'date'
       }, {
           name: 'quantity',
           type: 'number'
       }, {
           name: 'price',
           type: 'number'
       }],
       datatype: "array"
     };
    
     var adapter = new $.jqx.dataAdapter(source);
    
      var myJqxGrid;
      myJqxGrid = $("#jqxgrid").jqxGrid({
        width: 500,
        theme: 'energyblue',
        source: adapter,
      });
      $(window).unload(function(){
        myJqxGrid.jqxGrid('destroy');
      });
    });
    function refresh(){
      location.reload();
    }
    </script>
    </head>
    <body>
      <button onclick="refresh();">Refresh</button>
      <div id="jqxgrid-wrapper" >
        <div id="jqxgrid">
        </div>
      </div>
    </body>
    </html>

    The memory used increases roughly 15mb (scripts + objects) every reload. While I understand that using iframes like this is not optimal, this is not something I can change currently, and this issue is crippling to my implementation of jqxGrid.


    Dimitar
    Participant

    Hello francois,

    This may occur in older versions of Internet Explorer (<9), but not in modern browsers. Please note that our demos page uses the same iframe approach (each example is loaded in an iframe) and memory leaks are not observed .

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/


    francois
    Participant

    Hello Dimitar,

    This has been verified in both Chrome 42 and IE11.

    I believe this same issue occurs on your demos. Please see the attached screenshot of the growing memory. Every snapshot is taken after a right click -> reload frame.

    The worst thing is that IE11 does not wipe local memory when you change window.location to another domain or hard reload (f5, ctrl+r), and carries that memory for a very long time.

    Memory leak example


    Dimitar
    Participant

    Hello francois,

    Thank you for the clarification. However, this seems to be a browser/iframe-related issue rather than a jQWidgets one. Please check out the following Stack Overflow topic for more information and possible solutions: http://stackoverflow.com/questions/12128458/iframes-and-memory-management-in-javascript.

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/


    francois
    Participant

    Hello Dimitar,

    That the issue was iframe-related was my first guess, and I have spent some time trying to figure out a way to implement jqxGrid in an iframe (that can and will be reloaded) without success. I’ve done similar tests (loading libraries in the same iframe, and reloading them) without issues.

    Could you provide an example of jqxGrid inside an iframe that will not leak if the iframe is reloaded?

    I do believe it may be an issue with jqxGrid holding on to specific objects of jQuery. During my analysis, I did observe that the memory leak was much less important (3-4mb vs 15mb) if jQuery was not part of the iframe, but rather called from the parent of the iframe as seen below:

    ‘if(typeof $ === ‘undefined’) {
    var $ = jQuery = window.parent.$;
    jQuery = window.parent.jQuery;
    }’

    This however, can lead to unexpected behaviour of the code.


    Peter Stoev
    Keymaster

    Hi francois,

    Note that how and when Web Browsers manage IFrame’s memory and why the web browser does not release or calls when it finds necessary its garbage collector does not depends on jqxGrid. When jqxGrid’s destroy method is called, jqxGrid releases its resources and removes all DOM Elements and Event Handlers used by jqxGrid. jqxGrid then does not exist anymore and it’s the browser’s decision when to release its memory. All demos on our website are with Grids within IFrames. When you reload IFrame, the Web browser should release its memory and this as far as I know is asynchronous process based on its internal logic and that actually is different from browser to browser. This is not jqxGrid issue so we do not have any more comments to add about this.

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com


    andyrooger
    Participant

    Hi Francois,

    I found myself running into this issue too, took a long time staring at Chrome’s profiler to work out. For me, the problem was a mouseup event handler that jqxGrid adds to the parent document. This handler keeps essentially the entire grid in closure and is never removed (even with the destroy method).

    Unfortunately I’m not sure of any way to avoid this problem without adding a handler removal in jqxGrid, moving the grid out of the iframe or reloading the parent page. Hopefully a fix will make it into a future release…

    Cheers,
    Andy

    Memory leak using jqxgrid in an iframe #80630

    Ravi Gopalan
    Participant

    Hi,

    I also landed up in this problem. I saw few calls to top.window.document.addEventListener which doesn’t get removed when the jqxgrid destroy is being called.

    Iam not sure how to remove these event handlers as they aren’t getting removed even after unloading the iframe is removed/unloaded.

    If this can’t be removed, can u I get an explanation on why it is added only in the case of window.frameElement exists.

    Any help on this issue would be greatly appreciated.

    Regards,
    Ravi Gopalan

    Memory leak using jqxgrid in an iframe #80631

    Peter Stoev
    Keymaster

    All event handlers are removed when the Grid is destroyed. This is an old topic for old versions.

    Best Regards,
    Peter Stoev
    jQWidgets Team
    http://www.jqwidgets.com

    Memory leak using jqxgrid in an iframe #80633

    Ravi Gopalan
    Participant

    Hi,

    I checked the latest version on your site and that too has this window.top.document.addEventListener call which is why I had to raise this issue.

    I checked the remiveHandlers code as well and that removes all the handlers attached to this object and not the window.top.document handlers.

    Any help would be definitely appreciated.

    Regards,
    Ravi Gopalan

    Memory leak using jqxgrid in an iframe #80634

    Peter Stoev
    Keymaster

    Hi Ravi Gopalan,

    If you think that there is some event handler left out. Remove it using jQuery or JavaScript. Here is how to remove event handlers: http://api.jquery.com/off/

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com

    Memory leak using jqxgrid in an iframe #80637

    Ravi Gopalan
    Participant

    Hi,

    I tried using the $window.off to switch off the mouse up event handlers but it seems that event handlers added using addeventlisteners can be removed by eemiveeventlistener for which we need the reference to the function but jqxgrid adds an anonymous function. Do I am not able to remove the the event listener by jqury off.

    I am desperately looking for help from within jqxgrid.

    Regards,
    Ravi Gopalan

    Memory leak using jqxgrid in an iframe #80638

    Peter Stoev
    Keymaster

    Hi Ravi Gopalan,

    You can bind/unbind to any events using jQuery or plain JavaScript. We cannot help you more than giving you that advice.

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com

    Memory leak using jqxgrid in an iframe #98859

    dhroth
    Participant

    Ravi,

    I know this post was from a couple of years ago, but I was wondering if you were able to come up with a way to remove the event handler in question. I am running into the same issue where we are experiencing a memory leak when running the jqxGrid in an iframe. If you came up with a way to resolve this, I’d appreciate knowing how you did it.

    Thanks.

    Dave Roth

    Memory leak using jqxgrid in an iframe #98900

    dhroth
    Participant

    The functions listed below in jqWidgets code have calls to window.top.document.addEventListener and window.top.document.attachEvent. There are other cases that we don’t use. The pattern seems to be that the event handler is defined in a local variable within these functions so that window.top.document has a reference to the local code. It doesn’t appear that objects are being leaked, but instead the JavaScript code itself is being leaked. When the page in the Iframe unloads, the script code can’t be released because the top document has a reference to it (at least in IE).

    Our application has a static page containing an Iframe well where the guts of the application is loaded. As the user interacts with the application, the contents of the well Iframe are replaced. We have many instances of the grid within the application and each time a page with a grid is loaded into the Iframe, another 15-20 MB of memory is consumed as those event handlers are never released. After a few hours of working within the application our users would experience a browser crash which can be very costly when hospital clinicians are using these grids to see patient information when treating their patients.

    Here are the files that we use that exhibit this behavior.
    • jqxGrid.js – _addHandlers
    • jqxGrid.columnsresize.js – _handlecolumnsresize
    • jqxScrollbar.js – _addHandlers
    • jqxbuttons.js – createInstance – calls addHandler passing window.top.document

    Our only recourse was to override these functions with wrapper functions and in our wrapper stub out the window.top.document.addEventListener to suppress the registration of events there, then call the real jqx function, then put back the window.top.document.addEventListener. This was a hack that we really didn’t want to do, but didn’t have much choice in order to resolve the issues our users were experiencing.

    It seems that the approach that the jqx code is using to add the mouseup listeners to window.top.document is not an ideal approach since there is no way to clean up those event handlers because the definition of the event handlers is in local variables in the code. It would be of great benefit to the jqWidgets user community if this approach for adding the event listeners to window.top.document were changed and if the event listeners were cleaned up so that the consuming application doesn’t have to figure out a way to do it.

Viewing 15 posts - 1 through 15 (of 17 total)

You must be logged in to reply to this topic.