Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is eating my memory? (The SAW, JS mem usage edition)

So, I heard you can supposedly do all fancy real-time games using JS these days. And I'm no beginner at it, so I though I should give it a try. Wrote some micro (incomplete) physics engine with some collision detection, all sweet. Somewhat laggy though, expected GC interrupts. So tried to minimize any allocation, till I was unable to see anything that should allocate memory in game loop. No allocations => no cleanup I though. But here is what I get: enter image description here

Now, this is not neat at all. So I tried removing my stuff from game loop in various ways. Still SAW. So no I present you the complete code that generates this:

<html><body><script>
    function draw() { console.log(1); }
    ;(function () {
        function main(tFrame) { draw(); window.requestAnimationFrame( main ); }
        main();
    })();
</script></body></html>

Amazing? Well this uses requestAnimationFrame as it seems this is what should be used for smooth performance. At first I tried set interval like so:

<html><body><script>
    function draw() { console.log(1); }
    window.setInterval(draw, 0);
</script></body></html>

Exactly the same thing!

This seems completely unacceptable, but I have no ideas how to stop this SAW. I looked a lot about debugging memory and stuff, that was while I though that problem was in my drawing and updating functions. But these to snippets, have basically nothing, and yet they produce that memory patter. Maybe it is my browser? Or is it inescapable, and JS is unusable for anything real-time? I would like to believe that someone on the web knows something I don't as there are lot's of people promising wonders with JS. What am I doing wrong in these snippets?

EDIT: by the way removing console log changes nothing, in case anyone thinks thats the problem.

like image 414
morphles Avatar asked Mar 05 '15 20:03

morphles


1 Answers

Let's analyze that code a bit:

  • You are creating 3 functions on startup
  • You are creating 1 integer per draw call (60+ times per second)
  • You are logging once per draw call (which is super slow by the way)

Here is the performance of creating integers vs doing nothing vs logging in JavaScript:

Creating Integers versus logging them

http://jsperf.com/creating-integers

You are however right. After visiting an about:blank page and tweaking your code a bit I got some interesting data.

Code:

function draw() { 1; }

function main(tFrame) { 
    draw(); 
    window.requestAnimationFrame( main ); 
}

main();

Data:

GC JS Saw

This graph is fluctuating between 4.6MB and 5.2MB. Not such a big deal actually. Freeing half a megabyte of memory is really fast. Unfortunately, there is no way to avoid this. I tried the following:

var j = 1;

function draw() { j; }

And while there was less garbage to collect; GC still ran. On the plus side in both this example and the previous our code runs at 60fps at all times:

60fps... no logging

Moral of the story: logging is expensive. It is always expensive; javascript or not.

like image 111
Parris Avatar answered Nov 06 '22 03:11

Parris