SlideShare a Scribd company logo
Beyond 60 FPS
Chris Thoburn
@runspired
Ember + Mobile
@IsleOfCode
This is me, I recently took a timeout to wander a desert pondering the true meaning of Javascript.

This is the face I make when wondering what Tom Dale eats for breakfast.
Metal
Today I want to talk to you about system metal. The guts.
This is how it feels to conquer the world and deliver an app that runs smoothly. Pedal to the Metal.
But too often it turns out like this cyclist. 

It turns out that it’s hard to build optimized, performance focused applications without access to system metal.
What is our metal?
And how much access do we have?
When I began focusing on performance, I began asking this question.

Don’t worry, today isn’t going to be full of array or hash optimizations, it’s not about algorithms, Int32Arrays, Buffers, or Binary data.

Today, we’re going to talk a lot about requestAnimationFrame.
Doing Work Smarter
And we’re going to talk a lot about doing work smarter with requestAnimationFrame.

If you’ve never heard of requestAnimationFrame, I suggest you google it once we’re off of conference wifi, you may also want to consider a new home that’s not this
island, or a rock.
How does JS, JS?
But this isn’t a talk to tell you that requestAnimationFrame exists and why you should use it. Today we’ll dive deeper into what it is, how it functions, and how you should
be using it.
The Call Stack
For a lot of us, a stack trace such as this is our first experience with the call stack.
We entered the stack by calling aFunction, which called bFunction and so on until it hit the function that threw the error. Because invocation began with aFunction, the
stack, and thus the trace, lead back to aFunction.
The Callback Queue
This is usually called the “Event Queue”, but in order to not confuse it with actual events, or a concept we’ll introduce later called an “event frame”, we’re going skip on
calling it that.
setTimeout(fn, 0);
This function is fancy magic. We know that Javascript is single threaded and that we can bump some work down the line by wrapping it in this call.
setTimeout(fnC, 0);
setTimeout(fnB, 0);
setTimeout(fnA, 0);
setTimeout(fnD, 0);
setTimeout(fnE, 0);
We might even use it to delay a lot of work. We get that there’s some queue of functions to be invoked, and that doing this pushed execution of a function to the end of
that queue.

How does this work?
Let’s visualize. Let’s say we have a function “foo”.
And foo invokes setTimeout with the function bar.
Now, bar doesn’t immediately go onto the queue, instead it goes into this strange land of Web APIs, where a timer in a separate process is going to deliver it back to us
at the right time in case we say had called setTimeout with a number other than 0.
A timer kicks off, and at the right time, bar is sent to back of the queue.
And when the all the work from foo and from any other callbacks in front of this one completes, bar is invoked and becomes the start of a new call stack.

There are some concepts here for debugging asynchronous code “stack stitching” “async trace”
and we’re done!
Congrats, you know have a certificate in how JS works!
…but Wait!
requestAnimationFrame
How does requestAnimationFrame fit into this picture?
Ooof, there’s a lot going on in this picture, where to start.

For one, I’ve slyly renamed the callback queue to the “MacroTask” Queue. This just means these are higher level, but lower priority “jobs” or “tasks” that need to be
done. We’ve got a few waiting.

Off to the left, we’ve added a new purple box which we’ve called the Next AnimationFrame.
this time, foo calls requestAnimationFrame instead of setTimeout, and our web APIs see this as a new FrameTask.
and they schedule the job (baz) into the next AnimationFrame, a separate callback queue.
foo calls requestAnimationFrame several times, and each time a new job is pushed into the next AnimationFrame callback queue.

How will this flush?
I. Finish The Call Stack
II. Check if should flush AnimationFrame
I. Flush AnimationFrame
III. Do next MacroTask from MacroTask Queue
(repeat)
First, we complete the current call stack (all the work begun with foo).

Next, we check if it’s time to flush the AnimationFrame queue, and if so, we flush it.

Else, we do the next MacroTask, and repeat. We finish the callstack, check if we should flush the AnimationFrame, etc.

Let’s see this in action.
What happens if you requestAnimationFrame
during an Animation Frame flush?
if you’ve ever used raf, you already know the answer, but let’s see this quickly too.
When does AnimationFrame flush?
The Window.requestAnimationFrame() method tells
the browser that you wish to perform an animation
and requests that the browser call a specified function
to update an animation before the next repaint. The
method takes as an argument a callback to be
invoked before the repaint.

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
If you’ve ever dug into Chrome’s “performance tuning” documentation, you may have seen this diagram.
How much can we do inside it?
raf flushes ~ every (1000 / 60 - X) ms
Where X is the amount of time spent in the previous AnimationFrame flush. This means that if we take 10ms to flush, the next flush will begin only a few milliseconds
later.
Style is separate

AnimationFrame’s budge will adjust

Here, we’re doing JS and Layout outside of the AnimationFrame, but it’s legal to do it within it as well.
Awesome, let’s experiment with raf.
requestAnimationFrame and setTimeout cannot be used effectively together (you could schedule raf from the setTimeout callback though)
What is requestAnimationFrame good for?
(besides animation?)
FRP style updates: this is a snippet from Hammer.js 3.0 which is currently under active development.

Here, we don’t schedule work into raf, we use raf to poll new state and flush it.
This is a snippet from the next version of smoke-and-mirrors. This is a module that lets you add and remove scroll event handlers for an element.
But instead of binding an event to scroll, it passively polls the element’s offset and triggers the callback when it has changed.
More accurate Throttling
Throttling or debouncing work that should only happen once per X renders.
A Better IntersectionObserver
radar, within smoke-and-mirrors, is basically a richer IntersectionObserver, I’ve been considering turning it into a polyfill + additional features.
In poll mechanism for watching scroll, you may have noticed that I was flushing the callbacks inside the success callback of a resolved promise. This begs a question.
Promises
In Ember, we use a lot of promises for managing asynchronous behavior. How do they inter operate with setTimeout and raf?
We flushed our promise work before the console printed the return from our function. I promise you this is actually asynchronous, but don’t worry, I’ll explain.
Expanding Our Understanding
(again)
I. Finish The Call Stack
II. Flush MicroTask Queue
III. Check if should flush Render MacroTasks
I. Flush Render MacroTasks
IV. Do next MacroTask from Event Queue
(repeat)
A fuller picture
I. Promises
II. MessageChannel callbacks
III. MutationObserver callbacks
IV. setImmediate
MicroTask Implementations
A Kernel for the Web
So what’s this about a kernel for the web?

We want to get down to the system metal.
Houston, what’s our countdown at again?
We have a timing problem.

You do not know is the next macro task scheduled via setTimeout will trigger before or after the next AnimationFrame flush.

back burner (ember.run) flushes with setTimeout.

Ember’s rendering engine flushes by scheduling into backburner’s render queue.

This means, we do not know if our next render is before or after the next AnimationFrame flush.
Forced Layouts are a timing problem.
Layout is a lot like a computed promise. Various events and actions will invalidate it, but it isn’t recomputed until it’s requested.

Forced layouts happen when our JS code needs to read a layout related value and our layout is in an invalid state.
JS => L => JS => L => JS => L => Paint => Composite
L: Layout
FL: Forced Layout
JS: Javascript Logic (app code)
P: Paint
C: Composite
This is what the default state for most Ember apps is, multiple extra layouts 

Tying Ember’s render to setTimeout causes extra layouts.
JS => L => JS => FL =>
JS => L => JS => FL =>
JS => L => Paint => Composite
L: Layout
FL: Forced Layout
JS: Javascript Logic (app code)
P: Paint
C: Composite
Each time we did layout, we might also have needed to measure or alter something in the DOM, perhaps checking or modifying a class name, or maybe we wanted to
know the new dimensions or location of an object.

Now we additionally have multiple forced layouts to go with our extra layouts.
Increased asynchrony means decreased guarantees.
We do a lot of unnecessary work because of this.
I. (multiple) forced layouts
II. extraneous render flushes / diffs
III. misaligned read/write operations
IV. not all mutations and reads are equal
requestAnimationFrame is not necessarily better
you can still force layout

you want to batch your DOM reads and your DOM writes

not all DOM writes are created equal.

Abusing Frame MacroTasks can be as choppy and risky as setTimeout

if we aren’t organized.

Animation Frame’s flush stops the world,

but we do not know when.
Scheduling work via MacroTasks is slow
and error prone.
setTimeout often takes 4-5ms to flush

we have very poor guarantees of when
Scheduling work via MicroTasks is fast
but introduces order-of-operations issues.
We don’t know the order in which promises will be flushed.

We can’t control batching reads and writes.

Doing DOM work in a promise callback can quickly lead to Forced Layouts
Timing Implications
- our app is doing extra work
- the browser is doing extra work
- we’re increasing the likelihood of a
minor or a major GC event.
- we don’t know if work we
scheduled in RAF is happening
before or after the render we care
about.
We are even further away from the “Metal” now.
(not that we were very good at these things before either)
The frameworks we are building over have abstracted

rendering, in the process, we have lost control we need.
Major and Minor Garbage Collection events
stop the world and have unpredictable timing, but they
do have predictable causes!
What we really want, is a way to schedule work

to happen at the optimal time for what it is.
Igniter
I want to introduce you to a project I’ve been building called Igniter.
Event Frame Render Frame Measure Frame Idle Frame
- sync

- actions

- cleanup
- render

- afterRender

- cleanup

- destroy (legacy)
- measure

- affect
- gc

- query
schedule(‘sync’, () => {});
Why do we defer work, debounce, throttle, schedule?

- "do it at render"

- "do it in the right order"

- "do it at a better time"

- "do it later, just not now"

- "do this only once"

Igniter tries to answer these questions.
Event Frame
- sync

- actions

- cleanup
schedule(‘sync’, () => {});
EventFrame flushes as a micro task, and represents work that should be done asynchronously but immediately and in a better order.
Render Frame
- render

- afterRender

- cleanup

- destroy (legacy)
Render flushes within RAF, specifically at the beginning of RAF. This lets us avoid extra layouts and extra forced layouts that were present in the setTimeout version.
Measure Frame
- measure

- affect
Measure also flushes within raf, but is guaranteed to flush after render. It itself is separated into “measure” and “affect”, think “read” and “write”.
Idle Frame
- gc

- query
if you know that an operation is going to cause a significant GC and can be deferred, schedule it into the idle frame
Mechanics
Primary Advantages
I. Align work correctly
II. Avoid duplicated App work
III. Ease the Browser’s Workload
IV. Meaningful Stack Traces
V. Easier Experimentation
Secondary Advantages
requestIdleCallback polyfill
GC work

background network polling / worker polling / activity tracking / store management
requestLayoutFrame polyfill
Ultimately we shouldn’t be pushing layout into AnimationFrame like this, we need a new spec to bring us closer to the metal.
Streaming Templates
& Rendering Engines
Feature Potential
Smarter Animation Engines
Feature Potential
What is beyond 60fps?
Better CPU performance

Better Battery life

Even More Features
Is this what you were looking for?
Thanks :)

More Related Content

Similar to Beyond 60fps

Back To The Future.Key 2
Back To The Future.Key 2Back To The Future.Key 2
Back To The Future.Key 2gueste8cc560
 
Copy of repast javagettingstarted
Copy of repast javagettingstartedCopy of repast javagettingstarted
Copy of repast javagettingstarted
Nimish Verma
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
bobmcwhirter
 
maXbox Starter 45 Robotics
maXbox Starter 45 RoboticsmaXbox Starter 45 Robotics
maXbox Starter 45 Robotics
Max Kleiner
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScript
Amitai Barnea
 
Using MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB DayUsing MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB Day
hayesdavis
 
DPC 2007 My First Mashup (Cal Evans)
DPC 2007 My First Mashup (Cal Evans)DPC 2007 My First Mashup (Cal Evans)
DPC 2007 My First Mashup (Cal Evans)
dpc
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011tobiascrawley
 
Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009pauldix
 
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with DebuggingPART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
FastBit Embedded Brain Academy
 
JavaScript Engines and Event Loop
JavaScript Engines and Event Loop JavaScript Engines and Event Loop
JavaScript Engines and Event Loop
Tapan B.K.
 
Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2
Matthew McCullough
 
Memento Pattern Implementation
Memento Pattern ImplementationMemento Pattern Implementation
Memento Pattern ImplementationSteve Widom
 
Reactive programming with rx java
Reactive programming with rx javaReactive programming with rx java
Reactive programming with rx java
CongTrung Vnit
 
JavaScript Async for Effortless UX
JavaScript Async for Effortless UXJavaScript Async for Effortless UX
JavaScript Async for Effortless UX
재석 강
 
Animations on Fire - Making Web animations fast
Animations on Fire - Making Web animations fastAnimations on Fire - Making Web animations fast
Animations on Fire - Making Web animations fast
brianskold
 
TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011
Lance Ball
 
Capistrano, Puppet, and Chef
Capistrano, Puppet, and ChefCapistrano, Puppet, and Chef
Capistrano, Puppet, and Chef
David Benjamin
 
Building Hermetic Systems (without Docker)
Building Hermetic Systems (without Docker)Building Hermetic Systems (without Docker)
Building Hermetic Systems (without Docker)
William Farrell
 
Unleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
Unleashing Real-World Simulations: A Python Tutorial by Avjinder KalerUnleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
Unleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
Avjinder (Avi) Kaler
 

Similar to Beyond 60fps (20)

Back To The Future.Key 2
Back To The Future.Key 2Back To The Future.Key 2
Back To The Future.Key 2
 
Copy of repast javagettingstarted
Copy of repast javagettingstartedCopy of repast javagettingstarted
Copy of repast javagettingstarted
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
maXbox Starter 45 Robotics
maXbox Starter 45 RoboticsmaXbox Starter 45 Robotics
maXbox Starter 45 Robotics
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScript
 
Using MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB DayUsing MongoDB and a Relational Database at MongoDB Day
Using MongoDB and a Relational Database at MongoDB Day
 
DPC 2007 My First Mashup (Cal Evans)
DPC 2007 My First Mashup (Cal Evans)DPC 2007 My First Mashup (Cal Evans)
DPC 2007 My First Mashup (Cal Evans)
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
 
Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009
 
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with DebuggingPART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PART-3 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
 
JavaScript Engines and Event Loop
JavaScript Engines and Event Loop JavaScript Engines and Event Loop
JavaScript Engines and Event Loop
 
Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2
 
Memento Pattern Implementation
Memento Pattern ImplementationMemento Pattern Implementation
Memento Pattern Implementation
 
Reactive programming with rx java
Reactive programming with rx javaReactive programming with rx java
Reactive programming with rx java
 
JavaScript Async for Effortless UX
JavaScript Async for Effortless UXJavaScript Async for Effortless UX
JavaScript Async for Effortless UX
 
Animations on Fire - Making Web animations fast
Animations on Fire - Making Web animations fastAnimations on Fire - Making Web animations fast
Animations on Fire - Making Web animations fast
 
TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011
 
Capistrano, Puppet, and Chef
Capistrano, Puppet, and ChefCapistrano, Puppet, and Chef
Capistrano, Puppet, and Chef
 
Building Hermetic Systems (without Docker)
Building Hermetic Systems (without Docker)Building Hermetic Systems (without Docker)
Building Hermetic Systems (without Docker)
 
Unleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
Unleashing Real-World Simulations: A Python Tutorial by Avjinder KalerUnleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
Unleashing Real-World Simulations: A Python Tutorial by Avjinder Kaler
 

Recently uploaded

Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 

Recently uploaded (20)

Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 

Beyond 60fps

  • 2. Chris Thoburn @runspired Ember + Mobile @IsleOfCode This is me, I recently took a timeout to wander a desert pondering the true meaning of Javascript. This is the face I make when wondering what Tom Dale eats for breakfast.
  • 3. Metal Today I want to talk to you about system metal. The guts.
  • 4. This is how it feels to conquer the world and deliver an app that runs smoothly. Pedal to the Metal.
  • 5. But too often it turns out like this cyclist. It turns out that it’s hard to build optimized, performance focused applications without access to system metal.
  • 6. What is our metal? And how much access do we have? When I began focusing on performance, I began asking this question. Don’t worry, today isn’t going to be full of array or hash optimizations, it’s not about algorithms, Int32Arrays, Buffers, or Binary data. Today, we’re going to talk a lot about requestAnimationFrame.
  • 7. Doing Work Smarter And we’re going to talk a lot about doing work smarter with requestAnimationFrame. If you’ve never heard of requestAnimationFrame, I suggest you google it once we’re off of conference wifi, you may also want to consider a new home that’s not this island, or a rock.
  • 8. How does JS, JS? But this isn’t a talk to tell you that requestAnimationFrame exists and why you should use it. Today we’ll dive deeper into what it is, how it functions, and how you should be using it.
  • 10. For a lot of us, a stack trace such as this is our first experience with the call stack.
  • 11. We entered the stack by calling aFunction, which called bFunction and so on until it hit the function that threw the error. Because invocation began with aFunction, the stack, and thus the trace, lead back to aFunction.
  • 12. The Callback Queue This is usually called the “Event Queue”, but in order to not confuse it with actual events, or a concept we’ll introduce later called an “event frame”, we’re going skip on calling it that.
  • 13. setTimeout(fn, 0); This function is fancy magic. We know that Javascript is single threaded and that we can bump some work down the line by wrapping it in this call.
  • 14. setTimeout(fnC, 0); setTimeout(fnB, 0); setTimeout(fnA, 0); setTimeout(fnD, 0); setTimeout(fnE, 0); We might even use it to delay a lot of work. We get that there’s some queue of functions to be invoked, and that doing this pushed execution of a function to the end of that queue. How does this work?
  • 15. Let’s visualize. Let’s say we have a function “foo”.
  • 16. And foo invokes setTimeout with the function bar.
  • 17. Now, bar doesn’t immediately go onto the queue, instead it goes into this strange land of Web APIs, where a timer in a separate process is going to deliver it back to us at the right time in case we say had called setTimeout with a number other than 0.
  • 18. A timer kicks off, and at the right time, bar is sent to back of the queue.
  • 19. And when the all the work from foo and from any other callbacks in front of this one completes, bar is invoked and becomes the start of a new call stack. There are some concepts here for debugging asynchronous code “stack stitching” “async trace”
  • 20. and we’re done! Congrats, you know have a certificate in how JS works!
  • 23. Ooof, there’s a lot going on in this picture, where to start. For one, I’ve slyly renamed the callback queue to the “MacroTask” Queue. This just means these are higher level, but lower priority “jobs” or “tasks” that need to be done. We’ve got a few waiting. Off to the left, we’ve added a new purple box which we’ve called the Next AnimationFrame.
  • 24. this time, foo calls requestAnimationFrame instead of setTimeout, and our web APIs see this as a new FrameTask.
  • 25. and they schedule the job (baz) into the next AnimationFrame, a separate callback queue.
  • 26. foo calls requestAnimationFrame several times, and each time a new job is pushed into the next AnimationFrame callback queue. How will this flush?
  • 27. I. Finish The Call Stack II. Check if should flush AnimationFrame I. Flush AnimationFrame III. Do next MacroTask from MacroTask Queue (repeat) First, we complete the current call stack (all the work begun with foo). Next, we check if it’s time to flush the AnimationFrame queue, and if so, we flush it. Else, we do the next MacroTask, and repeat. We finish the callstack, check if we should flush the AnimationFrame, etc. Let’s see this in action.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34. What happens if you requestAnimationFrame during an Animation Frame flush? if you’ve ever used raf, you already know the answer, but let’s see this quickly too.
  • 35.
  • 36.
  • 37.
  • 38.
  • 40. The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint. https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
  • 41. If you’ve ever dug into Chrome’s “performance tuning” documentation, you may have seen this diagram.
  • 42. How much can we do inside it?
  • 43. raf flushes ~ every (1000 / 60 - X) ms Where X is the amount of time spent in the previous AnimationFrame flush. This means that if we take 10ms to flush, the next flush will begin only a few milliseconds later.
  • 44. Style is separate AnimationFrame’s budge will adjust Here, we’re doing JS and Layout outside of the AnimationFrame, but it’s legal to do it within it as well.
  • 46.
  • 47.
  • 48. requestAnimationFrame and setTimeout cannot be used effectively together (you could schedule raf from the setTimeout callback though)
  • 49. What is requestAnimationFrame good for? (besides animation?)
  • 50. FRP style updates: this is a snippet from Hammer.js 3.0 which is currently under active development. Here, we don’t schedule work into raf, we use raf to poll new state and flush it.
  • 51. This is a snippet from the next version of smoke-and-mirrors. This is a module that lets you add and remove scroll event handlers for an element.
  • 52. But instead of binding an event to scroll, it passively polls the element’s offset and triggers the callback when it has changed.
  • 53. More accurate Throttling Throttling or debouncing work that should only happen once per X renders.
  • 54. A Better IntersectionObserver radar, within smoke-and-mirrors, is basically a richer IntersectionObserver, I’ve been considering turning it into a polyfill + additional features.
  • 55. In poll mechanism for watching scroll, you may have noticed that I was flushing the callbacks inside the success callback of a resolved promise. This begs a question.
  • 56. Promises In Ember, we use a lot of promises for managing asynchronous behavior. How do they inter operate with setTimeout and raf?
  • 57.
  • 58. We flushed our promise work before the console printed the return from our function. I promise you this is actually asynchronous, but don’t worry, I’ll explain.
  • 60.
  • 61. I. Finish The Call Stack II. Flush MicroTask Queue III. Check if should flush Render MacroTasks I. Flush Render MacroTasks IV. Do next MacroTask from Event Queue (repeat) A fuller picture
  • 62. I. Promises II. MessageChannel callbacks III. MutationObserver callbacks IV. setImmediate MicroTask Implementations
  • 63. A Kernel for the Web So what’s this about a kernel for the web? We want to get down to the system metal.
  • 64. Houston, what’s our countdown at again? We have a timing problem. You do not know is the next macro task scheduled via setTimeout will trigger before or after the next AnimationFrame flush. back burner (ember.run) flushes with setTimeout. Ember’s rendering engine flushes by scheduling into backburner’s render queue. This means, we do not know if our next render is before or after the next AnimationFrame flush.
  • 65. Forced Layouts are a timing problem. Layout is a lot like a computed promise. Various events and actions will invalidate it, but it isn’t recomputed until it’s requested. Forced layouts happen when our JS code needs to read a layout related value and our layout is in an invalid state.
  • 66. JS => L => JS => L => JS => L => Paint => Composite L: Layout FL: Forced Layout JS: Javascript Logic (app code) P: Paint C: Composite This is what the default state for most Ember apps is, multiple extra layouts Tying Ember’s render to setTimeout causes extra layouts.
  • 67. JS => L => JS => FL => JS => L => JS => FL => JS => L => Paint => Composite L: Layout FL: Forced Layout JS: Javascript Logic (app code) P: Paint C: Composite Each time we did layout, we might also have needed to measure or alter something in the DOM, perhaps checking or modifying a class name, or maybe we wanted to know the new dimensions or location of an object. Now we additionally have multiple forced layouts to go with our extra layouts.
  • 68. Increased asynchrony means decreased guarantees.
  • 69. We do a lot of unnecessary work because of this. I. (multiple) forced layouts II. extraneous render flushes / diffs III. misaligned read/write operations IV. not all mutations and reads are equal
  • 70. requestAnimationFrame is not necessarily better you can still force layout you want to batch your DOM reads and your DOM writes not all DOM writes are created equal. Abusing Frame MacroTasks can be as choppy and risky as setTimeout if we aren’t organized. Animation Frame’s flush stops the world, but we do not know when.
  • 71. Scheduling work via MacroTasks is slow and error prone. setTimeout often takes 4-5ms to flush we have very poor guarantees of when
  • 72. Scheduling work via MicroTasks is fast but introduces order-of-operations issues. We don’t know the order in which promises will be flushed. We can’t control batching reads and writes. Doing DOM work in a promise callback can quickly lead to Forced Layouts
  • 73. Timing Implications - our app is doing extra work - the browser is doing extra work - we’re increasing the likelihood of a minor or a major GC event. - we don’t know if work we scheduled in RAF is happening before or after the render we care about.
  • 74. We are even further away from the “Metal” now. (not that we were very good at these things before either) The frameworks we are building over have abstracted rendering, in the process, we have lost control we need.
  • 75. Major and Minor Garbage Collection events stop the world and have unpredictable timing, but they do have predictable causes!
  • 76. What we really want, is a way to schedule work to happen at the optimal time for what it is.
  • 77. Igniter I want to introduce you to a project I’ve been building called Igniter.
  • 78. Event Frame Render Frame Measure Frame Idle Frame - sync - actions - cleanup - render - afterRender - cleanup - destroy (legacy) - measure
 - affect - gc - query schedule(‘sync’, () => {}); Why do we defer work, debounce, throttle, schedule? - "do it at render" - "do it in the right order" - "do it at a better time" - "do it later, just not now" - "do this only once" Igniter tries to answer these questions.
  • 79. Event Frame - sync - actions - cleanup schedule(‘sync’, () => {}); EventFrame flushes as a micro task, and represents work that should be done asynchronously but immediately and in a better order.
  • 80. Render Frame - render - afterRender - cleanup - destroy (legacy) Render flushes within RAF, specifically at the beginning of RAF. This lets us avoid extra layouts and extra forced layouts that were present in the setTimeout version.
  • 81. Measure Frame - measure
 - affect Measure also flushes within raf, but is guaranteed to flush after render. It itself is separated into “measure” and “affect”, think “read” and “write”.
  • 82. Idle Frame - gc - query if you know that an operation is going to cause a significant GC and can be deferred, schedule it into the idle frame
  • 84.
  • 85. Primary Advantages I. Align work correctly II. Avoid duplicated App work III. Ease the Browser’s Workload IV. Meaningful Stack Traces V. Easier Experimentation
  • 87. requestIdleCallback polyfill GC work background network polling / worker polling / activity tracking / store management
  • 88. requestLayoutFrame polyfill Ultimately we shouldn’t be pushing layout into AnimationFrame like this, we need a new spec to bring us closer to the metal.
  • 89. Streaming Templates & Rendering Engines Feature Potential
  • 91. What is beyond 60fps?
  • 92. Better CPU performance Better Battery life Even More Features
  • 93. Is this what you were looking for?