Question

I have the following function that create a jQuery Dialog and setup a jqGrid on it. My code runs within IE 8.

Every time I open the dialog I notice an increase of memory of the browser which is around 30 MB. When I close the dialog this memory is not freed.

Where do this code leaks?

function ShowData() {
    var gridID = "my_detail_grid";
    var pagerID = gridID + "_pager";
    var markup = $('<div style="display: none;">' +
                    '<input type="hidden" id="pclist_ownerID" name="pclist_ownerID" />' +
                    '<table id="' + gridID + '"></table>' +
                    '<div id="' + pagerID + '"></div>' +
                   '</div>');
    var owner = $('#pclist_ownerID', markup);
    markup.dialog({
        autoOpen: false, modal: true, stack: true, resizable: false, position: 'center',
        width: 860, height: 400,
        close: function (event, ui) {
            $(gridID).jqGrid('GridUnload');
            $(this).dialog('destroy');
            $(this).remove();
        }
    });

    $.ajax({
        url: 'MyWebService.asmx/GetAdditionalData',
        type: "post",
        dataType: "json",
        async: false,
        data: JSON.stringify({ objectID: objectID }),
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            var title = titlePrefix + data.d.objectname + " - " + data.d.period;
            markup.dialog("option", "title", title);
            owner.val(data.d.workgroupid);
        }
    });
    markup.dialog('open');
    var grid = $('#' + gridID);
    grid.jqGrid({
        url: 'MyWebService.asmx/MyMethod',
        colNames: [
            'Field1',
            'Field2',
            'Field3'
        ],
        colModel: [
            { name: 'Field1', index: 'Field1', width: 120, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false } },
            { name: 'Field2', index: 'Field2', width: 170, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false} },
            { name: 'Field3', index: 'Field3', width: 170, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false} }
        ],
        serializeGridData: function (postData) {
            if (postData.filters === undefined) postData.filters = null;
            return JSON.stringify(postData);
        },
        jsonReader: {
            id: "MyRecordID"
        },
        footerrow: false,
        userDataOnFooter: true,
        sortname: 'MyRecordID',
        sortorder: "asc",
        pager: $('#' + pagerID),
        rownumbers: true,
        gridComplete: function () {
            //this method just enable or disable the add/edit/delete based on conditions 
            reconfigPermissions();
        },
        gridview: true,
        autowidth: false,
        shrinkToFit: false,
        width: 830,
        height: 264
    })
    .jqGrid('navGrid', '#' + pagerID,
        {
            add: true, addtitle: 'Add Record',
            edit: true, edittitle: 'Edit Record',
            del: true, deltitle: 'Delete Record',
            refresh: false,
            search: false,  //searchtitle: 'Advanced search filters',
            addfunc: function () {
                // code for add
            },
            editfunc: function () {
               // code for edit
            }
        },
        { /*default settings for edit*/ },
        { /*default settings for add*/ },
        {
            /* settings for delete*/
            // define settings for Delete 
            mtype: "post", reloadAfterSubmit: true,
            url: 'MyWebService.asmx/Delete',
            resize: false,
            serializeDelData: function (postdata) {
                return JSON.stringify({ recordID: postdata.id });
            },
            afterSubmit: function (data, postdata) {
            }
        },
        {},
        {}
    )
    .jqGrid('navSeparatorAdd', '#' + pagerID, {})
    .jqGrid('navButtonAdd', '#' + pagerID, {
        caption: "", buttonicon: "ui-icon-search", position: "last", title: "Advanced search filters",
        onClickButton: function () {
            grid.searchGrid({
                sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge', 'bw', 'cn'],
                closeOnEscape: true, multipleSearch: true, closeAfterSearch: true, recreateFilter: true
            });
        }
    });
}

Thanks a lot for helping!

EDIT: No advice on this?

Was it helpful?

Solution

All sounds strange. jqGrid works not clean with memory. Nevertheless I don't think that increasing memory in 30 MB on after every opening of dialog could be explained by jqGrid only. The grid which you use don't contains rowNum. So the default value 20 (see the documentation) will be used. You don't use loadonce: true option, so 'MyWebService.asmx/MyMethod' used as the URL in the grid should returns about 20*4 cell values (3 columns + id column). Such response and all DOM structures created by jqGrid can't take 30 MB memory.

So I suppose that the reason of the problem could be other as jqGrid. You can use Fiddler, Developer Tools of IE or Chrome to trace HTTP traffic. I recommend you to verify responses from 'MyWebService.asmx/MyMethod' and from 'MyWebService.asmx/GetAdditionalData'. It can be that some response contains too much data. Reducing of data will not really solve the problem, but 30 KB of memory leaks will be not so important as leaks of the size 30 MB. By the way you can use userData and refresh the title of the dialog (make the same set of dialog option "title") inside of loadComplete. In the way you would save synchronous (async: false ???) Ajax call.

Additionally I would recommend you to change (temporary, only for the test) the datatype option from "json" to "local". No request to the URL 'MyWebService.asmx/MyMethod' will be done in the case and you could verify whether call of the method and filling the grid data are responsible for 30 MB which is your main problem.

You would recommend you to use deepempty: true option of jqGrid additionally.

If all your test will show that jqGrid is do responsible for memory leaks then you will have to replace $(gridID).jqGrid('GridUnload'); call to recursive cleaning of all DOM structures (cells and rows) created by jqGrid. I hope that it will be not needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top