I have a single-page web app that uses Knockout.js 2.2.1 to display information streaming from a server (using socket.io, although I don't think that matters). This app also contains a large data table, which is created from a JSON object using Knockout's foreach
bindings. (The table is big, but not enormous: 20 columns and 200 rows or so.)
Since the table is large, it can be opened/closed by the user by clicking buttons. The data <table>
is placed inside a <div>
element that I can hide/show using jQuery's .hide()
and .show()
methods (which essentially work by setting and clearing CSS display: none
on the <div>
).
All of this functionality works. However, I notice that after 'closing' (hiding) the big data table, Chrome's CPU usage jumps - all the way to 100% if the Knockout-generated table is big enough. What's more interesting is that this only happens after the user has clicked somewhere inside the <div>
element that contains the table when it is shown. When the table is hidden (and CPU usage is high), clicking somewhere else on the page will return CPU usage back to normal. The process will repeat at will.
Another possibly useful note: if I stop the streaming data from the server this problem doesn't happen (or, it's not noticeable in the CPU usage). There is a single Knockout view model on this page, which manages both the streaming data from the server and the creation of this data table from a JSON object. The two sets of data are otherwise completely separate - none of the changing data is displayed in the table, and the table contains no event bindings back to the view model. It's as if the streaming data update of the Knockout model is causing work on the data table even though none of the streaming data is bound to the table. And it does this only when the table is not displayed!
Quick summary:
.hide()
at startup in $(document).ready
, but is displayed using .show()
, after clicking a button, and can be hidden againOther relevant information:
Any ideas what's going on here, or suggestions for additional troubleshooting?
jsFiddle:
Example here: http://jsfiddle.net/CTYMv/6/
Look at CPU usage after loading the fiddle, it should be low. Click "Show Table", then click somewhere inside the div that pops up (gray background). Then click "Hide Table" - CPU usage will increase significantly. Then click anywhere else (white background), and CPU will return to normal.
As TechStacker explains, there are many possible explanations for high CPU usage in Chrome. These typically relate to your browsing behavior, including having too many tabs open at once, too many apps or browser extensions running and streaming high-quality video.
The most common causes for high CPU usage in your browser are: Too many apps running at the same time. Like browser extensions, which are small software packages that add functionality to your browser. Too many browser tabs open at the same time.
I think we can now argue this is a bug in webkit engine. This bug only appears when using css property display:none;
. Is it due to how GPU using webkit render hidden elements? Well, i still don't know...
SEE DEMO
This is the simplest workaround i can think of, this should not interfered with any of your other code: {e.g knockout observable}
CSS: {added pointer-events as suggested by Brandon}
.hidden{opacity:0;pointer-events:none} //don't use display:none here
JS:
//don't use hide/show jq methods as internally it set display none (fadeOut() methods too) $('#btn_show').click(function(){ $('#bigdatadiv').removeClass('hidden'); }); $('#btn_hide').on('click',function(){ $('#bigdatadiv').addClass('hidden') });
I'm aware this is just a workaround and that still not answering your question: why this is happening?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With