Topic
  • 3 replies
  • Latest Post - ‏2012-11-26T11:07:09Z by wisenose
SystemAdmin
SystemAdmin
6195 Posts

Pinned topic Severe Memory Leak

‏2012-11-14T17:17:23Z |
I am currently using quite a few widgets (datagrid embedded in a tab container, with multiple combo boxes, etc). Each time I refresh the screen (which triggers a DB query), IE 8 adds an extra 30MB memory consumption, thus after 10 refreshes, I am seeing about 600MB consumed by the single instance of IE. I tested briefly with Firefox, and found similar memory leaks (though not quite as significant). Between reading various forums and chatting with a few people, it was suggested that I might need to trigger the Java Garbage Collector and/or clear caches or destroy widgets. I am looking for some guidance on how to fix this issue.
Updated on 2012-11-26T11:07:09Z at 2012-11-26T11:07:09Z by wisenose
  • SystemAdmin
    SystemAdmin
    6195 Posts

    Re: Severe Memory Leak

    ‏2012-11-14T17:48:24Z  
    I was just provided this link, which I will look at in more detail later, but wanted to post this here.

    http://www.eclipse.org/forums/index.php/m/883394/
  • SystemAdmin
    SystemAdmin
    6195 Posts

    Re: Severe Memory Leak

    ‏2012-11-14T20:12:05Z  
    I was just provided this link, which I will look at in more detail later, but wanted to post this here.

    http://www.eclipse.org/forums/index.php/m/883394/
    Since my original posting (on the EDT forum) I've done some work on dealing with widget memory leaks though this is by no means complete. Here's where I've currently got to, but bear in mind this is EDT 0.8.1 EGL code.

    In each RUI widget/handler that subscribes to the InfoBus I define the following array:

    
    
    
    private ibSubscriptions any[]; 
    // InfoBus subscriptions register
    


    Then within the onConstructionFunction I create my InfoBus subscriptions as follows:

    
    
    
    private function start() ibSubscriptions.appendElement(InfoBus.subscribe(
    "core.ticker.services", processTickerService)); ibSubscriptions.appendElement(InfoBus.subscribe(
    "core.stocks.results.selected", resultSelected)); end
    


    I then create a destructor() function in the widget/handler to deal with removal of the InfoBus subscriptions plus any child widgets, you also need to consider any widgets that have been created but might not currently be children of another widget, such as discardButton in the sample below. This is a widget I define within my handler but only add to the ui if certain conditions are met. This is a practice that I will try and avoid in future; i.e. only define and create widgets that are appended as a child of another widget.

    
    function destructor() 
    // Destroy child widgets MyUtilLib.childrenDestructor(ui); 
    // Destroy widgets that may not be children of the ui MyUtilLib.childrenDestructor(discardButton); 
    // Remove infobus subscriptions 
    
    for(i 
    
    int from 1 to ibSubscriptions.getSize()) InfoBus.unsubscribe(ibSubscriptions[i]); end end
    


    I then have my own library function called childrenDestructor() that deals with specific widgets that have a destructor() function, not all of my widgets have or need a special destructor() function. MyUtilLib is my custom library whereas UtilLib is the the out of the box provided library. My library looks something like this:

    
    function childrenDestructor(widget widget in) kids widget[] = widget.children; 
    
    for(i 
    
    int from 1 to kids.getSize()) 
    // Destroy children of the child widget 
    
    case 
    // Handle MyResultsList when(kids[i] isa MyResultsList) list MyResultsList = kids[i] as MyResultsList; list.destructor(); 
    // Handle MyStockResultCell when(kids[i] isa MyStockResultCell) cell MyStockResultCell = kids[i] as MyStockResultCell; cell.destructor(); 
    // Handle MyStockResultDetail when(kids[i] isa MyStockResultDetail) detail MyStockResultDetail = kids[i] as MyStockResultDetail; detail.destructor(); 
    // Handle MyNoteContainer when(kids[i] isa MyNoteContainer) detail MyNoteContainer = kids[i] as MyNoteContainer; detail.destructor(); 
    // Handle everything else otherwise MyUtilLib.childrenDestructor(kids[i]); end 
    // Destroy the child widget UtilLib.destroyWidgetChildren(kids[i]); UtilLib.destroyWidget(kids[i]); end widget.removeChildren(); end
    


    Then within my application before I refresh any widget I'll issue the following. Note that this is (usually) only necessary on the container type widgets, as the destructor functions traverse its way down through child elements.

    
    MyUtilLib.childrenDestructor(ListBox);
    


    This has stopped most of the memory leakage issues I was seeing in my application but its not yet perfect. I've still got some leakage but I suspect that's more than likely because I've still to track down some widgets that a custom destructor function.

    My thoughts, going forward, are that 'memory leaks' really needs to be considered as a widget/handler is built and specific testing should be performed to make sure that each widget/handler doesn't leave any unwanted garbage behind. To implement garbage collection retrospectively is a big deal, especially when you're trying to track down garbage elements in a complex handler.

    If anybody has differing experience of garbage handling within EGL I'd be interested to know whether I'm on the right lines, perhaps there's a simpler solution out there.

    Richard
  • wisenose
    wisenose
    125 Posts

    Re: Severe Memory Leak

    ‏2012-11-26T11:07:09Z  
    Since my original posting (on the EDT forum) I've done some work on dealing with widget memory leaks though this is by no means complete. Here's where I've currently got to, but bear in mind this is EDT 0.8.1 EGL code.

    In each RUI widget/handler that subscribes to the InfoBus I define the following array:

    <pre class="jive-pre"> private ibSubscriptions any[]; // InfoBus subscriptions register </pre>

    Then within the onConstructionFunction I create my InfoBus subscriptions as follows:

    <pre class="jive-pre"> private function start() ibSubscriptions.appendElement(InfoBus.subscribe( "core.ticker.services", processTickerService)); ibSubscriptions.appendElement(InfoBus.subscribe( "core.stocks.results.selected", resultSelected)); end </pre>

    I then create a destructor() function in the widget/handler to deal with removal of the InfoBus subscriptions plus any child widgets, you also need to consider any widgets that have been created but might not currently be children of another widget, such as discardButton in the sample below. This is a widget I define within my handler but only add to the ui if certain conditions are met. This is a practice that I will try and avoid in future; i.e. only define and create widgets that are appended as a child of another widget.

    <pre class="jive-pre"> function destructor() // Destroy child widgets MyUtilLib.childrenDestructor(ui); // Destroy widgets that may not be children of the ui MyUtilLib.childrenDestructor(discardButton); // Remove infobus subscriptions for(i int from 1 to ibSubscriptions.getSize()) InfoBus.unsubscribe(ibSubscriptions[i]); end end </pre>

    I then have my own library function called childrenDestructor() that deals with specific widgets that have a destructor() function, not all of my widgets have or need a special destructor() function. MyUtilLib is my custom library whereas UtilLib is the the out of the box provided library. My library looks something like this:

    <pre class="jive-pre"> function childrenDestructor(widget widget in) kids widget[] = widget.children; for(i int from 1 to kids.getSize()) // Destroy children of the child widget case // Handle MyResultsList when(kids[i] isa MyResultsList) list MyResultsList = kids[i] as MyResultsList; list.destructor(); // Handle MyStockResultCell when(kids[i] isa MyStockResultCell) cell MyStockResultCell = kids[i] as MyStockResultCell; cell.destructor(); // Handle MyStockResultDetail when(kids[i] isa MyStockResultDetail) detail MyStockResultDetail = kids[i] as MyStockResultDetail; detail.destructor(); // Handle MyNoteContainer when(kids[i] isa MyNoteContainer) detail MyNoteContainer = kids[i] as MyNoteContainer; detail.destructor(); // Handle everything else otherwise MyUtilLib.childrenDestructor(kids[i]); end // Destroy the child widget UtilLib.destroyWidgetChildren(kids[i]); UtilLib.destroyWidget(kids[i]); end widget.removeChildren(); end </pre>

    Then within my application before I refresh any widget I'll issue the following. Note that this is (usually) only necessary on the container type widgets, as the destructor functions traverse its way down through child elements.

    <pre class="jive-pre"> MyUtilLib.childrenDestructor(ListBox); </pre>

    This has stopped most of the memory leakage issues I was seeing in my application but its not yet perfect. I've still got some leakage but I suspect that's more than likely because I've still to track down some widgets that a custom destructor function.

    My thoughts, going forward, are that 'memory leaks' really needs to be considered as a widget/handler is built and specific testing should be performed to make sure that each widget/handler doesn't leave any unwanted garbage behind. To implement garbage collection retrospectively is a big deal, especially when you're trying to track down garbage elements in a complex handler.

    If anybody has differing experience of garbage handling within EGL I'd be interested to know whether I'm on the right lines, perhaps there's a simpler solution out there.

    Richard
    IBM has fixed serious issues in the function destroyWidget some time ago. When you are using RBD8014 or higher, ánd you are using destroyWidget these issues are resolved. No need to create custom destruct functions. Destroying a widget will destroy the widget itself, including all contained widgets. However, when you are using the InfoBus you will still need to manually remove subscriptions before destroying a widget.
    Also read the recommendations on creating and destroying widgets in the RBD manual in chapter 'Rich UI memory management'. Can be very enlightning.....

    Guus