jQWidgets Forums
jQuery UI Widgets › Forums › Grid › grid performance with live updating
Tagged: jqxgrid knockoutjs
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
-
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.
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 StoevjQWidgets Team
http://www.jqwidgets.com -
AuthorPosts
Viewing 2 posts - 1 through 2 (of 2 total)
You must be logged in to reply to this topic.