jQWidgets Forums

jQuery UI Widgets Forums Grid grid performance with live updating

This topic contains 1 reply, has 2 voices, and was last updated by  Peter Stoev 11 years, 2 months ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
  • grid performance with live updating #53413

    johnemurray
    Participant
    Hi
    i've got a jqxgrid that is being updated by comet (iframe) and using knockoutjs observables and an observablearray
    but the performance is not great in chrome, and it's killing IE8 to the point i have to kill the browser, even with only one update every second.
    
    when i take out the jqxgrid and the knockout stuff, and i just have the comet stream create / search & update html dom elements, it works really well, so I would like to know how i can optimize the knockout/jqxgrid stuff if possible, so that it's useable.
    
    any suggestion?
    
    thanks very much
    
    john
    
    this is a sample of the json that's sent to the iframe:(in a loop, every two seconds, it toggles everything off, then on...)
    
    11:59:02,904 Sending to comet [serverGroup=london-aggregators, instrument=08, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,905 Sending to comet [serverGroup=london-aggregators, instrument=09, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,905 Sending to comet [serverGroup=london-aggregators, instrument=04, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,906 Sending to comet [serverGroup=london-aggregators, instrument=05, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,907 Sending to comet [serverGroup=london-aggregators, instrument=06, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,907 Sending to comet [serverGroup=london-aggregators, instrument=07, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,908 Sending to comet [serverGroup=london-aggregators, instrument=01, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,917 Sending to comet [serverGroup=london-aggregators, instrument=02, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,919 Sending to comet [serverGroup=london-aggregators, instrument=03, serverGroupState=[bad=false, map={2=true, 1=false}]]
    11:59:02,923 Sending to comet [serverGroup=london-aggregators, instrument=08, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,924 Sending to comet [serverGroup=london-aggregators, instrument=09, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,925 Sending to comet [serverGroup=london-aggregators, instrument=04, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,926 Sending to comet [serverGroup=london-aggregators, instrument=05, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,927 Sending to comet [serverGroup=london-aggregators, instrument=06, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,928 Sending to comet [serverGroup=london-aggregators, instrument=07, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,929 Sending to comet [serverGroup=london-aggregators, instrument=01, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,930 Sending to comet [serverGroup=london-aggregators, instrument=02, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:02,931 Sending to comet [serverGroup=london-aggregators, instrument=03, serverGroupState=[bad=false, map={2=false, 1=false}]]
    11:59:04,904 Sending to comet [serverGroup=london-aggregators, instrument=08, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,906 Sending to comet [serverGroup=london-aggregators, instrument=09, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,906 Sending to comet [serverGroup=london-aggregators, instrument=04, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,907 Sending to comet [serverGroup=london-aggregators, instrument=05, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,907 Sending to comet [serverGroup=london-aggregators, instrument=06, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,908 Sending to comet [serverGroup=london-aggregators, instrument=07, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,909 Sending to comet [serverGroup=london-aggregators, instrument=01, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,910 Sending to comet [serverGroup=london-aggregators, instrument=02, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,911 Sending to comet [serverGroup=london-aggregators, instrument=03, serverGroupState=[bad=false, map={2=false, 1=true}]]
    11:59:04,912 Sending to comet [serverGroup=london-aggregators, instrument=08, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,912 Sending to comet [serverGroup=london-aggregators, instrument=09, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,913 Sending to comet [serverGroup=london-aggregators, instrument=04, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,914 Sending to comet [serverGroup=london-aggregators, instrument=05, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,917 Sending to comet [serverGroup=london-aggregators, instrument=06, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,920 Sending to comet [serverGroup=london-aggregators, instrument=07, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,922 Sending to comet [serverGroup=london-aggregators, instrument=01, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,922 Sending to comet [serverGroup=london-aggregators, instrument=02, serverGroupState=[bad=true, map={2=true, 1=true}]]
    11:59:04,923 Sending to comet [serverGroup=london-aggregators, instrument=03, serverGroupState=[bad=true, map={2=true, 1=true}]]
    
    and here is my html (redacted, trimmed etc!)
    
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <title>london-aggregators Subscribed Instruments</title>
            <link rel="shortcut icon" type="image/png" href="/assets/images/favicon.png">
            <script src="/assets/javascripts/jquery-1.9.0.min.js" type="text/javascript"></script>
            <script src="/assets/jquery-ui/1.9.0/ui/jquery-ui.js" type="text/javascript"></script>
            <link href="/assets/jquery-ui/1.9.0/themes/base/jquery-ui.css" rel="stylesheet" type="text/css">
            <link href="/assets/stylesheets/controller.css" rel="stylesheet" type="text/css">
    
            <script type="text/javascript" src="/assets/countdown.min.js"></script>
            <script type="text/javascript" src="/assets/moment.min.js"></script>
            <script type="text/javascript" src="/assets/knockoutjs/knockout-2.2.1.js"></script>
            <script type="text/javascript" src="/assets/knockoutjs/knockout.mapping-2.4.1.js"></script>
            <!-- BEGIN - SCRIPTS AND LINKS RELATED TO JWQUERY -->
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxcore.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxbuttons.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxcalendar.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxcheckbox.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdata.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdata.export.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdatetimeinput.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdropdownlist.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.columnsresize.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.edit.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.grouping.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.aggregates.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.export.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.pager.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.selection.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxgrid.sort.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxsplitter.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxexpander.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxinput.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxlistbox.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxcombobox.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxmenu.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxnumberinput.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxpanel.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxscrollbar.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxtooltip.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxvalidator.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxwindow.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdatetimeinput.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxcalendar.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxdatetimeinput.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxradiobutton.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/jqxknockout.js"></script>
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/jqwidgets/globalization/globalize.js"></script>
            <link rel="stylesheet"        href="/assets/jqwidgets-ver3.0.3/jqwidgets/styles/jqx.base.css" type="text/css" />
            <script type="text/javascript" src="/assets/jqwidgets-ver3.0.3/scripts/gettheme.js"></script>
            <link href="/assets/stylesheets/jqx.coba-navigation.css" rel="stylesheet" type="text/css">
            <script type="text/javascript" src="/assets/javascripts/wrapperScript.js" charset="utf-8"></script>
        </head>
    <body class="body">
            
            
    
    <script type="text/javascript" src="/assets/javascripts/serverStatejsroutes"></script>
    <script type="text/javascript">
    
        $(document).ready(function () {
    		//this dynamically creates the iframe to subscribe to events
            var route = jsRoutes.controllers.ServerStateController.liveView('london-aggregators');
            var url = route.url;
    
    		ifrm = document.createElement("IFRAME");
    		ifrm.setAttribute("src", url);
    		ifrm.id="comet";
    		ifrm.style.width = 40+"px";
    		ifrm.style.height = 10+"px";
    		document.body.appendChild(ifrm);
    
            //this function defines the class structure, methods and constructor for the model we will attach to our jqxgrid
            //items is a constructor parameter
            var GridModel = function (items) {
                //it contains an observable array, initialised with whatever comes into as the ctor parameter
                this.items = ko.observableArray(items);
                this.items.extend({rateLimit:2000});
                //define a method that can take in a datawrapper js object
                this.updateValue = function (dataWrapper) {
                    var found = false;
                    $("#jqxgrid").jqxGrid('beginupdate');
                    var match = ko.utils.arrayFirst(this.items(), function(item) {
                        return dataWrapper.key === item.key;
                    });
                    var newInstrumentStateWithKey= new InstrumentStateWithKey(dataWrapper);
                    if (match) {
                        ko.mapping.fromJS(newInstrumentStateWithKey, match);
                 //       $("#messages").append('<li>' + new Date().getMilliseconds() + ' '+ newInstrumentStateWithKey.key+' change '+newInstrumentStateWithKey.bad + '</li>')
                    }
                    else {
                        this.items.push(newInstrumentStateWithKey);
                        this.items.sort(function(left, right) { return left.key == right.key ? 0 : (left.key < right.key ? -1 : 1) });
                //        $("#messages").append('<li>' + new Date().getMilliseconds() + ' '+newInstrumentStateWithKey.key+' add '+newInstrumentStateWithKey.bad + '</li>')
                    }
                    $("#jqxgrid").jqxGrid('endupdate');
                };
            };
            //no initial data - we will update using json that comes in on the initial snapshot
            var initialData = [];
            //gridModel is a variable in the window context
            window.gridModel = new GridModel(initialData)
            //this gets knockout up and running, and will associate the gridModel with the jqxGrid
            ko.applyBindings(window.gridModel,document.getElementById('jqxgrid'));
    
        });
    
        //this defines a new class that uses Knockout mappings plugin
        //it will have all the fields that dataWrapper.value has (which is an ServerGroupState), as observables
        //and also the key from the dataWrapper
        var InstrumentStateWithKey = function(dataWrapper) {
            ko.mapping.fromJS(dataWrapper.value.map, {}, this);
            this.key = dataWrapper.key;
            this.bad = dataWrapper.value.bad;
        }
    
        // Called for each Comet message
        // data is a json node
    
        window.dataReceived = function(dataWrapper) {
            var dataType=dataWrapper.messageType
            var classType = dataWrapper.classType
            var value = dataWrapper.value
            if (dataType === "BrowserHeartbeat") {
                //a heartbeat from the controller to the browser. just update the text on the page
                var formattedDate = new Date(value.timestamp).toLocaleString()
                $("#timestamp").text(formattedDate)
                $("#serverName").text(value.serverName)
            }
            else if (dataType === "ServerGroupState" ) {
             //   $("#messages").append('<li>' + new Date().getMilliseconds() + ' '+ dataWrapper.key+' notify '+dataWrapper.value.bad + '</li>')
                gridModel.updateValue(dataWrapper);
    
            }
            else{
    
            }
    
            //try to trim the iframe content size
            var iFrame = document.getElementById("comet"),
                    iFrameDocument = iFrame.contentDocument || iFrame.contentWindow.document;
            iFrameDocumentElement =iFrameDocument.documentElement
            var headElementsArray = $("head",iFrameDocumentElement)
            var headElement = headElementsArray[0]
            var scriptElementsArray = $("script",headElement)
            if (scriptElementsArray.length > 1) {
                headElement.removeChild(scriptElementsArray[0]);
            }
    
        }
    
    </script>
    
    <div>
    <span id="timestamp">watch this space</span>
    <span id="serverName">who are you?</span>
    </div>
    <br>
    
    <div data-bind="jqxGrid: {
                                source: items,
                                disabled: false,
                                autoheight: false,
                                height: 600,
                                width: 1200,
                                theme: getDemoTheme(),
                                editable: false,
                                selectionmode: 'none',
                                columns: [
                                    { text: 'Instrument', dataField: 'key', width: 200  },
                                    { text: 'Bad', dataField: 'bad', width: 200  },
                                    { text: '1', dataField: '1', width: 90 },
                                    { text: '2', dataField: '2', width: 90  }
                                ]
                            }" id="jqxgrid">
    </div>
    
    <ul id="messages">
    
        </body>
    </html>
    
    when in the chrome debugger i see lots and lots of these:
    
    <div class="jqx-menu-wrapper" style="z-index:20000; border: none; background-color: transparent; padding: 0px; margin: 0px; position: absolute; top: 0; left: 0; display: block; visibility: visible;" id="menuWrappergridmenujqxgrid"></div>
    
    being added to the dom. i can't see where they come from.
    grid performance with live updating #53426

    Peter Stoev
    Keymaster

    Hi john,

    If you need performance for live updates, use the Grid in virtual mode and don’t use middle layers like KO.

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.