senäh

17senäh und so…

HTML/CSS/JS
24. Jul 2011
Kommentare: 5

Bessere Loops mit requestAnimationFrame()

Kategorien: HTML/CSS/JS | 24. Jul 2011 | Kommentare: 5

Das schöne daran neue Dinge zu lernen, ist unter anderem die Tatsache, dass man schnelle Fortschritte macht 🙂 Nach jeden neuen Tag ist man etwas besser als den Tag zuvor. So finde ich ständig Tipps und Hilfestellungen mit denen ich meine „abgeschlossenen“ Projekte verbessern und aufwerten kann, um zum Beispiel Performance zu gewinnen. Dank FPS-Zählern lässt sich der Erfolg noch wunderbar in Zahlen ausdrücken. Kommen wir zum heutigen Thema: Wie erhöhe ich in wenigen Zeilen Code meinen BouncingBalls-Performance-Test um 20%? 😉

Auf Paul Irish’s Seite habe ich einen netten Hinweis darauf gefunden, wie man klassische Animations-Loops vom Browser steuern lässt, anstatt über Zeitintervalle. Dadurch wird die Performance erhöht, der Update wird mit anderen Updates gesynct (z.B. JavaScript-Animation mit CSS-Animationen) und der Loop wird pausiert, wenn man in ein anderen Tab wechselt (weniger CPU/GPU-Auslastung und dadurch Batterie sparen). Wow! Ihr schafft das mit wenigen Zeilen Code und bei nicht unterstützten Browsern kann auf die klassische Variante zurückgegriffen werden.

Screenshot Canvas-Performancetest

Screenshot Canvas-Performancetest

Um es zu testen habe ich mein BouncingBalls-Beispiel geschnappt und im BallManager.js ein paar Zeilen Code geändert.

Aus

function startLoop()
{
    setInterval(draw, 33); // 33 milliseconds = ~ 30 frames per sec
}

wurde

function startLoop()
{
    requestAnimFrame(startLoop);
    draw();
}

// requestAnim shim layer by Paul Irish
// thanks to http://paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function()
{
    return  window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function(/* function */ callback, /* DOMElement */ element)
            {
                window.setTimeout(callback, 1000 / 60); // 16 ms = ~60 fps
            };
})();

Das war es. Der Rest bleibt identisch. Hier ist das Live-Beispiel.

Testet es selbst. In der alten Version habe ich bei 2000 Bällen ~30 fps. Jetzt habe ich bei 2000 Bällen ~37 fps, also rund 20% mehr.

 

EDIT:

Entschuldigt die Verwirrung. In der alten Loop waren die fps künstlich auf 30 limitiert. Voll kommen klar, dass hier keine 37 fps zustande kommen. Ich hatte da irgendwo einen Denkfehler. Nichtsdestotrotz ist die Performance der zweiten Loop besser. Wenn man die Anzahl der Bälle erhöht und so die Performance unter 30 fps fällt, wird das sichtbar.

Autor: Pipo

...kommt ursprünglich aus der Designerecke, ist aber im Laufe seines Studiums in die Webentwicklung gestolpert. Kann sich seit dem nicht so richtig entscheiden wo er hingehört und wagt deswegen vielleicht die Flucht nach vorne in ein komplett neues Gebiet. Vielleicht Management? Niemand weiß es. Auch er nicht.