SlideShare ist ein Scribd-Unternehmen logo
1 von 94
Downloaden Sie, um offline zu lesen
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 :)

Weitere ähnliche Inhalte

Ähnlich wie 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 javagettingstartedNimish 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 TorqueBoxbobmcwhirter
 
maXbox Starter 45 Robotics
maXbox Starter 45 RoboticsmaXbox Starter 45 Robotics
maXbox Starter 45 RoboticsMax Kleiner
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScriptAmitai 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 Dayhayesdavis
 
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 DebuggingFastBit 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.2Matthew 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 javaCongTrung 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 fastbrianskold
 
TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011Lance Ball
 
Capistrano, Puppet, and Chef
Capistrano, Puppet, and ChefCapistrano, Puppet, and Chef
Capistrano, Puppet, and ChefDavid 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 KalerAvjinder (Avi) Kaler
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxRTS corp
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingShane Coughlan
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencessuser9e7c64
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Anthony Dahanne
 

Kürzlich hochgeladen (20)

Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conference
 
Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024Not a Kubernetes fan? The state of PaaS in 2024
Not a Kubernetes fan? The state of PaaS in 2024
 

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?