I do a lot of ajax calls on my site and was using jQuery 1.4.2 until I noticed that it was leaking. It was leaking with IE, Firefox, and Chrome. After some investigation I found the IE fix for it. I tried it but it didn't fix it for any of the three browsers. I then found a posting on here where the person compared Yahoo's Javascript library to jQuery. Yahoo's didn't leak for that person. I switched to Yahoo's and it did stop the leak in IE and Firefox (I even used the Firefox leak addon). But Chrome is still leaking. Chrome builds up to around 200MB of memory and then crashes my tab. The ajax call is every second. It takes about an hour before the tab crashes. If I leave the page the memory is released. Again, IE and Firefox the problem is now gone.
What's the best way of determining where the problem is for Chrome? I looked for an add-on but haven't found one yet. I also did some searching on Google but haven't really found anything there either. I took heap snapshots but I just see big numbers next to (closure) and (code).
I liked the Firefox one (Leak Monitor), made it easy to see the problem. Anything like that for Chrome or any suggestions for finding the leak?
Use Chrome's built-in Heap Profiler in DevTools (press F12 in Chrome then go to Profiles tab):
Here you can find how to test it:
link
The framework isn't causing the leak, it's your code. Let me guess at what your code looks like.
$.get('//url/',function(){
//lets do fun stuff!
function(){
//more fun expensive stuff for the browser to do
}
};
//A more efficient way (doesn't create closures)
function expensivefn(){
//Do expensive stuff here
}
$.get('//url',expensivefn);
This is only one possible way your code could be inefficient. I don't commonly create pages that infinitely loop, usually I look for a set amount of time then ask the user if he still wants to poll. The loop you are using could be creating unnecessary closures just like the above example. For example,
//Bad!
setInterval(function(){
//Expensive stuff
}, 1000)
//Good
function expensivestuff(){
//Expensive stuff
}
setInterval(expensivestuff,1000);
Related
I have a strange situation and I need some ideas.
"Sometimes" I have a performance issue when I am destroying a dom/web component. I am using Google Chrome.
I wanted to see with the profiler what is going on and strangely if I enable the Performance Profiling everything goes well and fast.
I guess it might be an extension I use that is causing the issue, but how can I identify it, without enable/disable all of them?
This screenshot will give you an idea about the response time differences. The second request takes longer (there is more to destroy).
We are developing a single-page web app with ZK which constantly communicates with server and updates parts of its screens. Updating can be as frequent as 1s. During these updates, references to large ammounts of JS objects are lost and those objects have to be cleaned by garbage collector eventually.
As far as we've figured out, Chrome only runs its garbage collector on inactive tabs. This is a problem for us, because the app's tab is usually active and almost never refreshed, thus JS objects never get collected. If left active for enough time, the tab eventually crashes (Aww Snap message).
We need to initiate garbage collection manually. So far we've tried running Chrome with --js-flags="--expose-gc" and running gc(), but it throws an exception:
ReferenceError: gc is not defined
This doesn't happen on Firefox -- memory usage is more or less a constant.
Force refreshing the page is not an option.
We would be grateful for any and all suggestions.
EDIT: we've tried running window.gc() and gc() both on Chrome versions 23.0.1271.97 m and 25.0.1364.2 dev-m
You can fetch code of Chrome Dev Tools, modify it so that ProfilerAgent.collectGarbage(); is called every now and then (it's a code that is called when you click 'Collect Garbage' button on the Timeline panel) and run Chrome with your version of DevTools using --debug-devtools-frontend flag.
However, this solution is quite extreme, try it only when you get really desperate. Till then, I propose profiling your application and checking out why v8 decides not to clean the garbage (or can't clean the garbage). Timeline panel of DevTools will help you out with this. Start with checking if 'Collect Garbage' button at the bottom of this panel really does its job, if not - you probably have a memory leak (at least, according to v8). If so, try leak-finder-for-javascript.
[EDIT] I removed info about chrome extension, as it turns out that gc() can be called from webpage code when --js-flags="--expose-gc" is used. At least on my 23.0.1271.64.
In Chrome Developer Tools you have "Timeline" section, from around Chrome 53. you have there button looks like Garbage Can. clicking on it and it forcing the garbage collector to run.
Update:
The GC button moved to Performance Tab in more recent versions of Chrome.
I found a solution. Apparently Chrome leaks DOM nodes, at least in the current version (26.0.1410.65 right now)
I recorded dev tools timeline in my app and it showed the Event Listeners count going up and down rhythmically along with my app screen's contents, but the DOM Node count was steadily increasing over time, until the tab crashed.
I tried the latest Chrome Canary (28.0.1500.3) and they seem to have fixed the problem. DOM Node count graph now follows the same rhythmic pattern as the Event Listeners.
The thing that gets me is...why doesn't gmail ever crash? I usually keep a tab open for weeks at a time...
The project I'm working on involves a "planning" screen, which is entirely made with backbone.js (the other pages of the app are not).
My issue is that from times to times, chrome freezes and the web view stop responding to any interaction. Sometimes, I can manage to quit chrome itself, but usually the controls does not answer either.
I'm pretty convinced this is related to the js code. It seems to me that when a script takes too much time, or loops indefinitely, Chrome can detect this and interrupt the script. However, since this is not the case, I'm thinking that too many js objects stay in memory.
Whatever the cause is, I would like to know which chrome dev tools can help me here. While I'm not a beginner in js, asides setting breakpoints and calling console.log, I have no idea how to debug JS apps. I'm not opposed to use another browser if the dev tools are more suited.
Thanks a lot for your time !
FTR : This is a rails 3.2.8 app, using mongodb, & Backbone.js 0.9.2. The js code is written in coffeescript. This issue happened on my macbook air 2012 running mountain lion, as well as on the client machine which runs on windows 7. The issue appeared at least on chrome 22 & 23.
Using the Javascript CPU profiler, I was able to find the group of functions that seems to be responsible for the freezing.
I'm still open to any advice/ressource on debugging javascript code.
Make a console.log in the loop and check if its the same point freezing on all chrome versions. There is a limit see Browser Javascript Stack size limit.
Maybe add some code? Because there could be some memory leaks especially with event handlers!
What I would do is the long and weary approach to getting your hands dirty with console.log. --- in this case.
In your case, and THX for the hint by the way (finding the offender with the CPU profiler, I'll try that next time round), I guess the offenders might be some functions "callbacking" themselves .. probably via some sort of event-handling/bubbling/callback-combination.
What happens then usually is that it just doesn't recognize the endless-loop, because the callback-stack is kinda "broken". Therefor it will never throw a browser-error.
If you have any luck, it doesn't kill the browser quick enough to kill the console. I did have that at times, the console killed (remaining silent), the coffeescript files not even loaded in the debugger (I use a JIT-coffee-to-js-translator as in JS-MVC) ... the page frozen or not doing anything ...
So, if indeed you are lucky and the debugger spits out your console.logs you can thereby guess where your unwanted loop is hiding. Just by looking at the repeated order of the output statements.
of course you know you can set breakpoints right? even conditional breakpoints
I'm currently struggling a bit untangling a similar sounding loop - i guess in case of emergency some alert() calls in your code would at least slow the loop down
or maybe some wait calls (bad idea)
my loop is running so fast I loose my console log!
I've lately been running into odd issues, which I'm starting to think are related to resource starvation in the browser.
In FF:
I'd been testing one of our web apps and suddenly things that should disappear after a couple seconds stopped disappearing. I tracked back to setTimeout just flat out refusing to work. After reloading the browser it was all clear, no issues.
In IE:
I regularly see issues where IE will refuse to do transparency all the sudden, simply reloading the page clears this up.
In both:
Though I can't say its related for sure, I see unexplainable behavior, things along the lines of variables not being available (undefined) when they should be.
Both browsers also show a steady increase in memory usage over time (memory leaks).
The javascript in the web app is heavy and it is a single load page (making those memory issues mentioned all the more painful). There are lots of in-efficiency, and various things that make one say "why would you do that?".
Has anyone encountered such things? Can you point out general resources that will help identify and resolve these issues?
You could try running your application against the Chrome Profiler http://code.google.com/chrome/devtools/docs/overview.html. You can profile the CPU and get snapshots of the browser heap, that should help locate any rogue stuff.
If your application is designed to work with the Internet Explorer: The Developer Toolbar also has a profiler.
I wrote this small game at http://amarnus.me/games/dodge. Now if you trying playing the game in both Firefox and Chrome, you would clearly notice that it is significantly slower in Firefox. You can call it an unintentional cheat code, yes. ;-)
So my question is - Is this because of a slower Javascript engine in Firefox when compared to Chrome's? Or does it have something to do with bad coding? (In my defence, I am a Javascript newb)
Assuming that it is the former, then is this not a point against (disadvantage of) HTML5 games? (The ones using the <canvas> tag like mine)
Firefox is slower than chrome in javascript. However, I believe that it's also slower using the canvas-tag. This will probably improve with ff4 (have you tried the beta?).
There is also a nes emulator out on the web somewhere using js and canvas, and it runs in about 30fps on chrome (if I remember about correctly), but only about 10 in ff.
Time is probably your best friend :-P, though you can alwasy try to optimize.
I believe that browser-games will come in time, but it's not ready as of yet to anything too advanced. Maybe about the time ie12 comes out :-P.
[Edit]
Btw: I tried the game in FF4b1, and I thought it ran great. Probably not as fast as in chrome, but not far from it :).
In order to get help you might consider providing a non-minified version of your script.
I see that there are 8ms setIntervals in your code. As mentioned above, Firefox never goes below 10 ms (yet). Playing your game in FFox 4 it is very enjoyable, though. I saw two very small hickups that clearly were caused by garbage collection. Chrome has an edge over the Fox in that regard. Even though SpiderMonkey (that handles GC in Firefox) has improved dramatically from 3.5 to 3.6 it's still not good enough for many games. In 4.0 it is a lot better, but still not quite as good as in Chrome or Opera. (It is being worked on.)
Playing the game and looking briefly at your code, I see no complexity that would cause Firefox not to be able to handle what's going on. Also Firefox 4 has hardware accelerated Canvas that is marginally faster than IE9 and a lot faster than Chrome.
There is a notion on the web that Chrome is faster than Gecko when it comes to canvas, but that is because people rarely profile their pages. In fact, canvas in Firefox 3.6 is already at least as fast as in Chrome, but many tests don't show it since the JavaScript is slower. (And some JavaScript tests are slower because Firefox does not handle the test harness well.)
All this leads to lots of confusion and misinformation. The bottom line is that your game should be OK in Firefox 4. You should see if there is anything you can do to avoid triggering unnecessary GC. E.g. are you re-using variables or creating unnecessary new ones?
However, in Opera 10.53 it was not enjoyable. Not because Opera could not keep up with the speed, but since instead of moving the bottom piece, it was kept stationary and the whole playing field moved instead. (I managed to go to level 17 in my first try in spite of this.) In Opera 10.6 the page fails to load properly.
You probably need to debug your code - or perhaps file a bug with Opera if it's a regression. (I'll tweet this to get their attention.)
I'd blame a large part of it on setTimeout and setInterval having a ~10ms minimum in browsers such as IE and Firefox. This was originally adopted to stop pages from consuming the entire CPU should they naively use 0ms to run as fast as possible. Chrome launched without a limit but is now moving to a 4ms minimum to match the recommendation in HTML5.
John Resig has some awesome posts investigating setTimeout limits and accuracy.
Mozilla browsers can actually tell you how late (or early!) they're running with each setInterval call. Check out the MDC setTimeout article (google "mdc settimeout" and check out the grey note in the syntax section).
Apart from timer problems, Firefox is just generally slower in JS execution (for now at least) and it feels as if Skia (Chrome's graphics lib) is just faster at rasterising too.
Hope this helps :)
(I originally had a bunch of useful links here, but it's my first post and the spam filter slapped me down.)
jQuery animate does something similar to your DOM object movement.
I would look into their code and see how they do the actual movement, it's probably the most efficient way since it's built in jQuery.
Chrome is designed to have a faster Javascript engine.
I don't think it says anything about HTML5 games. You will always find users with faster or slower setups than others, be it hardware, software or a user's personal habit of keeping many applications running at once. If your game were written in Flash or Java, then a user with slower hardware would see a similar slowdown.
You may be able to make changes to your code in order to speed it up. I haven't examined it in great detail, but I see you have constructs like if(dodge.goRight == true .... Although not a source of slowness, this does hint that you may not have used the optimal solution everywhere.
You can test your browser javascript engine with IE site.
http://ie.microsoft.com/testdrive/
They assert to the highest speed javascript engine they have with IE9
Try out this technique: setTimeout with a shorter delay
Let me know if it helps. I'm kinda curious now. :)
Good luck!