Jump to content

HTML 5 canvas with Melon causing high fan speeds


Recommended Posts

I'm on an older Melon JS 2.1.1, and a 2013 Macbook pro and am experiencing very high fan speeds whenever I load my HTML5 canvas game with Melon.

I'm trying to diagnose the fan speed. I don't drop FPS (they remain at 59/60), but I get sluggishness on my laptop in general (e.g., trying to manipulate CSS or elements in Chrome Dev tools while the game is running).

Attached below are pics of a ) the debug output from Melon and b ) top 20 or so CPU hogs from Chrome dev tools memory analysis.

Any other suggestions / direction I should look at for this? 


Screen Shot 2017-07-21 at 12.18.43 AM.png

Screen Shot 2017-07-21 at 12.34.42 AM.png



Screen Shot 2017-07-21 at 12.45.06 AM.png

Screen Shot 2017-07-21 at 12.46.47 AM.png

Link to comment
Share on other sites

The high fan speeds can happen with large canvases and high refresh rate. It's because your CPU is doing all of the work to render and draw the scene. WebGL helps a lot in this area because the GPU starts doing most of the drawing work. The CPU is still heavily involved, but not quite as taxed.

DOM modification is also pretty heavyweight, which is why frameworks like React implement a virtual DOM... Even though you're not doing that work in the game, you're still asking the browser to do a lot of work when changing colors and layout.

One tip I can provide is capturing a profile in the Performance tab of Chrome Dev Tools. You already shared a screenshot of the summary wheel chart from such a capture. Importantly, you'll get a flame graph representing function call times, which you can zoom into and inspect. For 60fps, you should expect each frame takes 16.667ms. When you inspect the flame graphs at the frame-level (mouse wheel to zoom in) you can gather a sense of what is taking the most time, and optimize around it.

I grabbed a profile of about 10 seconds on my relatively powerful VR desktop. Here's the summary:


This shows that over the 10 second run, the CPU was idle for 9.5 seconds. (91.7% idle) This was captured from the game in the website background, which uses WebGL. The more idle, the lower your fan speed.

This screenshot is zoomed in on a single frame, and shows how much time each function call took. The entire frame was completed in 0.87ms. And the drawing alone took just 0.32ms. In other words, it performs incredibly well.


One thing I find curious here is that Chrome is showing the animation frame timing is about 20ms instead of 16.667ms. That means I'm not getting a full 60fps. I'm actually getting 50fps. Must be a bug in Chrome or my GPU drivers ... During each frame, my CPU and GPU are both completely idle for 19ms, and active for less than 1ms. Here's what it looks like zoomed out a bit. Look at all that idle time, and still 20ms between each frame!


In any case, this tool can help you diagnose performance issues. IMHO, WebGL will help a bit, but you have an unusually high amount of time spent doing "other" things in Chrome. Which is an obnoxiously named category, but it could include extensions, even the Chrome Dev Tools, or other tabs doing things in the background.

Link to comment
Share on other sites

  • 2 weeks later...

This is off-topic, but I thought I would quickly followup here to explain the 20ms requestAnimationFrame that I was seeing; My VR desktop has a GeForce GTX 1080, and my monitor supports 100 Hz with G-sync enabled. On the other hand, RAF only supports 60 fps (60 Hz) max (which is 16.667ms minimum between each callback). So Chrome lowers its frame rate to exactly half of my monitor refresh rate, which is 50 Hz.

There is currently an open issue at w3c for supporting variable refresh rates, it appears to be targeted for HTML 5.2: https://github.com/w3c/html/issues/375

A timer-based workaround is quite easy if you don't mind hard-coding the refresh rate (or providing a UI to set the refresh rate manually). For example, adding this code prior to loading melonJS will monkeypatch requestAnimationFrame to 144 Hz (which is 6.944ms minimum between each callback):

(function () {
    var lastTime = 0;
    var frameDuration = 1000 / 144; // or 60, 75, 90, 100, 120, etc.

    requestAnimationFrame = function (callback) {
        var currTime = window.performance.now();
        var timeToCall = Math.max(0, frameDuration - (currTime - lastTime));
        var id = window.setTimeout(function () {
            callback(currTime + timeToCall);
        }, timeToCall);
        lastTime = currTime + timeToCall;
        return id;

    cancelAnimationFrame = function (id) {

    window.requestAnimationFrame = requestAnimationFrame;
    window.cancelAnimationFrame = cancelAnimationFrame;


Link to comment
Share on other sites

  • 4 weeks later...

@Parasyte Sorry just seeing this now! I got no notification from this forum that you had responded. 

Thank you for the detailed response. I'm still using 2.1.1 because my codebase has grown quite a bit and do not have the time to upgrade to the latest. Two reasons for not upgrading:

- I'm not sure how much work would be involved and how many breaking changes there are from 2.1.1

- I haven't looked over the updates yet. Are there major changes that I could benefit from in the areas of performance?

Also, I understand DOM manipulations are heavy. I should be utilizing Melon's Canvas API more, but am not familiar enough with it and feel a lot more comfortable with things like overlays and GUI components using the DOM. 

Link to comment
Share on other sites

  • 2 weeks later...

There have been a few improvements to the WebGL renderer since 2.1.1, lots of bug fixes with Audio and TMX maps, performance improvements all over the place (especially the particle emitters), plus some new features like the GamePad API. It is probably going to be a lot of work upgrade; I was just curious. But we do maintain an upgrade guide to help with the transition.

Link to comment
Share on other sites

  • 5 months later...

@Parasyte, I'm ultimately changing the direction of the game anyway so it's a good time to upgrade from Melon 2.x to 5.1.

At this juncture I'm also evaluating Phaser (2.6.3 and 2.10+ CE) vs Melon 5.1. 

Phaser JS looks like a more developed community especially with its 2.10 Community Edition, but I've heard a number of complaints around the underlying pixi engine causing high CPU usage and frame rate drops when you add a lot of layers (10+ I believe).

From your perspective, what are the key benefits of Melon 5.1 over Phaser 2.10+ CE (or even 2.6.3 latest team release)?

I care about performance and easy-to-use API.

Link to comment
Share on other sites

@Parasyte Also RE: "The high fan speeds can happen with large canvases and high refresh rate. It's because your CPU is doing all of the work to render and draw the scene. WebGL helps a lot in this area because the GPU starts doing most of the drawing work" - i plan on having full screen canvas. Using 5.x melon, how do I ensure the high refresh rate work is offloaded to the GPU instead of CPU?


My game should be played in Firefox and Chrome, both GPU accelerated browsers by default... is this offloading to the GPU then automatic? Like I said my game will have many layers and I care a lot about performance.  Im usually able to maintain high FPS like i said, but cpu speeds up and is sluggish from cpu side (speaking from my experience previously on 2.1)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...