Forum

November 2nd, 2014
A A A
Avatar

Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

The forums are currently locked and only available for read only access
sp_Feed Topic RSS sp_Related Related Topics sp_TopicIcon
SubGrid options and Memory Leaks
28/02/2012
14:50
Avatar
caradees
Member
Members
Forum Posts: 8
Member Since:
28/02/2012
sp_UserOfflineSmall Offline

Hello,

Attached below is a basic jqGrid example – to simulate auto-refresh conditions. I observed that all you need to do is add this option of subGrid (subGrid: true,) in the jqGrid options to start a memory leak. Without this options the iexplore leaks dissapear.

Am I not using the grid options correctly ? Attached is the code for this HTML page. This is observed in IE 8 when the start button is clicked after creating the Grid using the Create click.

I am using jqGrid 4.1.2 and jQuery 1.6.2.

Appreciate your inputs/suggestions on this.

-Caradee

——–

<!DOCTYPE html>
<html>
<head>
<title>jqGrid Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1″ />
<link type="text/css" href="themes/overcast/jquery-ui-1.8.15.custom.css" rel="stylesheet" />
<style type="text/css">
  .oddRow {
    background: none;
    background-color: antiquewhite;
  }
</style>
<script type="text/javascript" src="jquery-1.6.2.js"></script>
<script type="text/javascript" src="jquery-ui-1.8.15.custom.min.js"></script>

<link type="text/css" href="plugins/jqGrid/css/ui.jqgrid.css" rel="stylesheet" />
<script type="text/javascript" src="plugins/jqGrid/i18n/grid.locale-en.js"></script>
<script type="text/javascript" src="plugins/jqGrid/jquery.jqGrid.js"></script>
<script type="text/javascript">
  var rowCount = 200, dataGrid;
  var interval = 5, running = false;
  var data = [];
 
  $(function()
  {
    $('#lnk_create').click(doCreate);
    $('#lnk_load').click(doLoading);
    $('#lnk_start').click(doStart);
    $('#lnk_stop').click(doStop);
    $('#lnk_remove').click(doUnload);
  });

  function invoke()
  {
    if(!running)
    {
      return;
    }      
    $('#lnk_load').click();
    setTimeout(invoke, 1000 * this.interval);
  }

  function getList()
  {
    var list = [];
    for(var index = 1; index < rowCount; index++)
    {
      list.push({
        id: index,
        invdate: '2007-10-' + index,
        name: 'test' + index,
        note: 'note' + index,
        amount: '200.00',
        tax: '10.00',
        total: '210.00'
      });
    }
    return list;
  }

  function doLoading()
  {
    data = getList();
    dataGrid.clearGridData();
    for(var index = 1; index < data.length; index++)
    {
      dataGrid.addRowData(index, data[index]);
    }
  }

  function doUnload(ev)
  {
    ev.preventDefault();
    dataGrid.GridUnload();
    delete dataGrid;
  }

  function doStop(ev)
  {
    ev.preventDefault();
    running = false;
  }

  function doStart(ev)
  {
    ev.preventDefault();
    if(running)
    {
      return;
    }
    running = true;
    invoke();
  }

  function doCreate(ev)
  {
    ev.preventDefault();
    dataGrid = $("#list", $('#main')).jqGrid({
      datatype: "local",
      colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'],
      colModel:[
        {
          name:'id',
          index:'id',
          width:60,
          sorttype:"int"
        },
        {
          name:'invdate',
          index:'invdate',
          width:90,
          sorttype:"date"
        },
        {
          name:'name',
          index:'name',
          width:100
        },
        {
          name:'amount',
          index:'amount',
          width:80,
          align:"right",
          sorttype:"float"
        },
        {
          name:'tax',
          index:'tax',
          width:80,
          align:"right",
          sorttype:"float"
        },
        {
          name:'total',
          index:'total',
          width:80,
          align:"right",
          sorttype:"float"
        },
        {
          name:'note',
          index:'note',
          width:150,
          sortable:false,
          search: false
        }
      ],
      // subGrid: true,
      deepempty: true,
      altRows: true,
      altclass: 'oddRow',
      rowNum: 10,
      rowList:[10,20,30],
      multiselect: true,
      pager: '#pg',
      viewrecords: true,
      width: 600,
      height: 300,
      autowidth: true,
      recordtext: "Rec {0} – {1} of {2}",
      caption: "Invoice Data………"
      });
      $("#list", $('#main')).jqGrid('navGrid','#pg', {
        edit:false,
        add:false,
        del:false
      });
    }
</script>
</head>
<body>
  <h2>jqGrid Example2 with Auto-Refresh</h2>
  <div id="main">
  <div id="toolbar">
    <a href="#create" id="lnk_create">create</a>
    &nbsp;||&nbsp;
    <a href="#start" id="lnk_load">load</a>
    &nbsp;||&nbsp;
    <a href="#start" id="lnk_start">start</a>
    &nbsp;||&nbsp;
    <a href="#stop" id="lnk_stop">stop</a>
    &nbsp;||&nbsp;
    <a href="#remove" id="lnk_remove">remove</a>
  </div>
  <table id="list"></table>
  <div id="pg"></div>
  </div>
</body>
</html>

29/02/2012
14:50
Avatar
Nisha09
New Member
Members
Forum Posts: 1
Member Since:
29/02/2012
sp_UserOfflineSmall Offline

Hello,

Even I am also facing the same issue with jqGrid 4.1.2 and jQuery 1.6.2...In each refresh of grid data(Using timer), iexplore process  memory usage increases approximately by 4 to 5MB when I enable the subGrid: true option of JQGrid. Due to this memory leak, the performance of that IE browser instance degrades as time progresses. Any suggestions/inputs regarding this issue is highly appreciated.

@caradees, did you get any input/solution for this issue.

01/03/2012
13:06
Avatar
tony
Sofia, Bulgaria
Moderator
Members

Moderators
Forum Posts: 7721
Member Since:
30/10/2007
sp_UserOfflineSmall Offline

Hello,

Maybe you will need to use a certain DOCTYPE.

Using jQuery 1.6.x is not recommended.

Please look at thiew website the problems related to IE.

Regards

For professional UI suites for Java Script and PHP visit us at our commercial products site - guriddo.net - by the very same guys that created jqGrid.

05/03/2012
15:15
Avatar
caradees
Member
Members
Forum Posts: 8
Member Since:
28/02/2012
sp_UserOfflineSmall Offline

tony said:

Hello,

Maybe you will need to use a certain DOCTYPE.

Using jQuery 1.6.x is not recommended.

Please look at thiew website the problems related to IE.

Regards


Tony,

Thanks for that input. We experimented with various document types and observed the memory usage patterns of jqGrid with the subGrid set to true within IE8. Here is what we found (please note that we used a customized setData method within jqGrid 4.3.1 - will post that function later once we have something concrete)

jQuery version used was still 1.6.2

DT1 - <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

DT2 - <!DOCTYPE HTML>

DT3 - <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

DT4 - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

As you can see from the graph below that setting it to DT3 (Quirks mode) did not cause the leaks as in the other document modes.

Image Enlarger

Interesting. Will post more as we find with our experiments. Thanks for putting our heads into that direction, Tony !!!

Appreciate your help and inputs. Please do add your thoughts/comments on this.

12/03/2012
14:51
Avatar
caradees
Member
Members
Forum Posts: 8
Member Since:
28/02/2012
sp_UserOfflineSmall Offline

Enabling Quirks mode is changing the way the application is being rendered and moving forward since HTML5 might become the standard I would like to not enable quirks mode in IE - but I need to enable the jqGrid subgrid to implement a feature.

Is it possible that the new rows being inserted where the subgrid is present is not being garbage collected by IE.

The mainGrid being  a parent to the subGrid might be making a reference to the subGrid making the subGrid to not be GC'ed thus not allowing the mainGrid also to be GC'ed when the table is destroyed (since IE still uses refCount on DOM and JS objects before GC'ing them).

Any thoughts on this please help.

15/03/2012
10:31
Avatar
caradees
Member
Members
Forum Posts: 8
Member Since:
28/02/2012
sp_UserOfflineSmall Offline

I started to dig into the jqGrid code for addSubGrid in jqGrid 4.1.2 to check what might be causing the Internet Explorer leak when subGrids are enabled. Finally we narrowed down to this line of code that binds the click event to the cell
   $(ts.rows[i].cells[pos]).bind('click', function(e) { /* SOME CODE HERE */ });

If this line is commented - the leaks in IE stops.

So I added an unbind immediately after the bind to event happens as follows(I even tried the other two options 2 & 3 also)

                       $(ts.rows[i].cells[pos]).unbind('click'); //1
                       // $(ts.rows[i].cells[pos]).unbind('click', false); //2
                       // $(ts.rows[i].cells[pos]).unbind();  // 3

Unbind did not help and the leak continued.

Along with that I added a ts = null; statement at the end of the function addSubGrid .

This has brought down the memory leak to about ~350KB per refresh of 1000 records.

But I still do not understand why unbind does not reverse what is done by the bind method.

Can anyone please tell me if I am missing something here in solving this memory leak issue ?

Thanks !

15/03/2012
11:43
Avatar
caradees
Member
Members
Forum Posts: 8
Member Since:
28/02/2012
sp_UserOfflineSmall Offline

Regarding my last post,

Please disregard - ts = null; option that breaks the functionality of the jqGrid subGrid (we will now be unable to click on the + sign)

Binding the click event to each of the 10 rows in the jqGrid takes up about 35Kb. Since I have 10 rows per page my implementation my application is leaking by 350Kb per refresh.

I am not sure how to release this memory that is being consumed by this statement

$(ts.rows[i].cells[pos]).bind('click', function(e) { /* SOME CODE HERE */ });

Somebody please help Cry

15/03/2012
20:32
Avatar
OlegK
Germany
Member
Members
Forum Posts: 1255
Member Since:
10/08/2009
sp_UserOfflineSmall Offline

Hello caradees,

You made many experiments to localize the problem and to find a workaround. One more test you can do if you suspect that

$(ts.rows[i].cells[pos]).bind('click', function(e) { /* SOME CODE HERE */ });

is the origin of the problem. The code set 'click' event on every '+' icon. The last line of the event handler is return false; which stop event propagation. If you remove (comment) the code you can use

onCellSelect: function (rowid, iCol, cellcontent, e) {
    if (iCol === 0) { // or 1 of you use rownumbers
        doTheSame(e);
    }

The method doTheSame can be the same as from /* SOME CODE HERE */. The difference of the approatch is that you save some memory already because of making only one event handler for 'click' instead of setting 'click' event on every '+' icon. See my answer which discuss the problem.

Additionally I recommend you never ever use addRowData method to fill the grid bacause it's one of the most slow method to add the data to the grid. Every call of addRowData method follows to recalculating of positions of all elements curently existing on the page. The more elements you add with previous calls of addRowData method in the loop the slowly will every next call.

If you have an array of data you can use datatype: 'local' with data: myArrayWithData or datatype: 'jsonstring' with datastr: myData to add the data. In case of usage datatype: 'jsonstring' the myData must be not a string. It can be parsed data in the same format as typical JSON data (see here). In both cases you will not need to call clearGridData explicitly. The previous data will be cleared automatically.

You should set gridview: true in any way. If you use datatype: 'local' with data: myArrayWithData or datatype: 'jsonstring' withdatastr: myData to add the data then the whole grid body will be created first and then all the rows will be placed on the page as one operation. In the case you will not have the slow effect which I described before about addRowData method. In my personal opinion the gridview: true should be default setting of every jqGrid.

All this is not connected with your main problem of memory leaks, but I just can't see how uneffective is your code.

Best regards
Oleg 

25/04/2012
10:19
Avatar
yejinzai
New Member
Members
Forum Posts: 1
Member Since:
25/04/2012
sp_UserOfflineSmall Offline

Hi Oleg,

I'm kinda confused on what to do based on your comment where $(ts.rows[i].cells[pos]).bind('click', function(e) { /* SOME CODE HERE */ }); is written on the jquery source file while onCellSelect: function (rowid, iCol, cellcontent, e) { will be written on the client code. Can you englighten me?

I'm creating another grid as subgrid and users experience memory error after a number of continuous expanding. Below is my sample code if needed.

subGrid: true,
subGridRowExpanded: function(subgrid_id, row_id) {
    var id = $("#list").getCell(row_id, 'Code');
    var divcontaner_id;
    var subgrid_table_id;
    var pager_id;

    subgrid_table_id = subgrid_id + "_t";
    pager_id = "p_" + subgrid_table_id;
    divcontaner_id = "d_" + subgrid_table_id;

    $("#" + subgrid_id).html("<div id='" + divcontaner_id + "'><table id='" + subgrid_table_id +   "'></table><div id='" + pager_id + "' class='scroll'></div></div>");
    $("#" + subgrid_table_id).jqGrid({…

Thanks,

Kris

25/04/2012
12:58
Avatar
OlegK
Germany
Member
Members
Forum Posts: 1255
Member Since:
10/08/2009
sp_UserOfflineSmall Offline

Hi Kris,

I agree that I expressed me not clear enough in my last post. What I suggest is mostly the code optimization of addSubGrid method. The method will be called on every sorting, paging and filling the grid having subgrid. The method contain the part of code which enumerate all rows of the grid and add 'click' handler to every "expand/collapse" button. The more rows one has the more memory will be used. Additional problem which follow to additional increasing of used memory is the fact that one calls

$(ts.rows[i].cells[pos]).bind('click', function() {...})

inside of the while loop. The code of the click-handler function can be different for every i. So the code produce everytime different instances of the click-handler function. It gets more additional memory.

To see another option how one can implement the same I recommend you to look in the code of the implementation of 'click' handler here or event better to look small code of 'mouseover' and 'mouseout' event habdles from here and here. The events will be bound on the whole grid. The e.target shows the exact origin of the event. Using $(e.target).closest("tr.jqgrow") for example one can get the row where the event took place.

So if you'll comment the code from the lines

$(ts.rows[i].cells[pos]).bind('click', function(e) { /* SOME CODE HERE */ });

in the addSubGrid method you can include the code from the 'click' handler inside of the 'click' event bound to the grid (see here). I understand that it's not very simple. You did many experiments with jqGrid. So as one more experiment you can place the 'click' code from addSubGrid method inside of onCellSelect (or inside of new 'jqGridCellSelect' event handler). In the way you could verify whether you will have the same problems as before with memory leaks or you will have at least less size of the leaks.

Best regards
Oleg

P.S. I still don't understand why the usage of <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> elimenats the memory leaks.

Forum Timezone: Europe/Sofia

Most Users Ever Online: 715

Currently Online:
36 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

OlegK: 1255

markw65: 179

kobruleht: 144

phicarre: 132

YamilBracho: 124

Renso: 118

Member Stats:

Guest Posters: 447

Members: 11373

Moderators: 2

Admins: 1

Forum Stats:

Groups: 1

Forums: 8

Topics: 10592

Posts: 31289

Newest Members:

, razia, Prankie, psky, praveen neelam, greg.valainis@pa-tech.com

Moderators: tony: 7721, Rumen[Trirand]: 81

Administrators: admin: 66

Comments are closed.
Privacy Policy   Terms and Conditions   Contact Information