2

I have some questions concerning JavaScript loops.

Questions :

  • Why does a JavaScript loop freeze the browser
  • Why is the drawing slow even do it's running at 1 draw every 1ms and it's drawing the simplest thing!
  • What's the solution? flash is dying, what do we do now?

Here is the canvas code to try for yourself :

<!doctype html>
<html>
<head>
</head>
<body>
    <canvas id="c" width="400" height="400"></canvas>
    <script type="text/javascript">

        var c = document.getElementById( 'c' );

        ctx = c.getContext( '2d' );

        var x = 100;

        ctx.fillStyle= '#f00';

        function loop()
        {
            ctx.fillRect( x, 100, 20, 20 );

            ++x;
        }

        setInterval( loop, 1 );
    </script>
</body>
</html>
4
  • 1
    How beast is your computer? doesn't sound too powerful Commented Nov 13, 2011 at 0:18
  • 2
    @AustinHenley it's going to be replaced by HTML5 though, because it's a more suitable tool Commented Nov 13, 2011 at 0:27
  • same as this post stackoverflow.com/questions/25612452/… Commented Sep 2, 2014 at 17:44
  • don't use setInterval() replace it with window.requestAnimationFrame() Commented Sep 2, 2014 at 17:50

3 Answers 3

10

Why does a JavaScript loop freeze the browser ( does not happen in C++ )

JavaScript is single threaded. The state of the DOM cannot change whilst javascript code is running or race conditions would occur. This means no drawing / reflow.

Why is the drawing slow even do it's running at 1 draw every 1ms and it's drawing the simplest thing!

It's not running at 1ms, it's running at 10ms because browsers do not allow you to loop that tightly.

What's the solution? flash is dying, what do we do now?

Use requestAnimationFrame and run your game at 60 FPS, why do you need more?

Example using (webkit) requestAnimationFrame which runs smoothly for me.

Sign up to request clarification or add additional context in comments.

2 Comments

(webkit/mozilla)RequestAnimationFrame do not truly sync with the refresh rate, it's merely a refresh rate-based time interval callback. By that reckoning, rendering at twice the frame rate could see an improvement in the smoothness of the rendering, where it wouldn't if it was perfectly timed. The problem is that JavaScript as you find it in the browser was never designed to do the high performance multi-threaded tasks that we would really like to do in the browser. That's not a shortcoming of JavaScript, merely the use of JavaScript as a single-threaded event sink in the browser.
"JavaScript is single threaded." not true javascript is multi-threaded developer.mozilla.org/en-US/docs/Web/Guide/Performance/…
2

One millisecond is an extremely short interval.
It's such a short interval that your code will be running in the UI thread almost continually, leaving the browser unresponsive.

You need to leave pauses to give the user time to interact with the page.

Use an interval of at least ten, and preferably one hundred, milliseconds.

6 Comments

That's not it at all. setInterval does not make the browser unresponsive.
@Raynos: While the code in the interval runs, the browser is unresponsive. If there isn't any time when code isn't running, the browser won't respond.
but browsers have a minimum set timeout to avoid this exact issue. This minimum is 10. Again this isn't the issue. And the browsers can do plenty reflow rendering in 10 milliseconds
@Raynos: Is that limit standard? Where is that specified? I wasn't aware of that.
Looks like it's 4ms for Firefox : mxr.mozilla.org/mozilla-aurora/source/dom/base/…
|
0

The reason of the framerate drop and eventually the browser freeze occurs because of the memory occupied by the canvas element. I already answered this question. You can find the thread here.

Each time you draw something to the canvas that operation is saved to the path of the canvas. This path occupies more memory each time you draw something on the canvas. If you don't empty the path of the canvas you will have framerate drops. For example look at the execution time difference between your javascript and the javascript below which clears the canvas path,

var c = document.getElementById( 'c' );
ctx = c.getContext( '2d' );
var x = 100;
ctx.fillStyle= '#f00';

function loop()
{
    ctx.beginPath(); 
    ctx.fillRect( x, 100, 20, 20 );

    ++x;
}
setInterval( loop, 1 );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.