SlideShare a Scribd company logo
1 of 60
UNDERSTANDING THE V8 RUNTIME TO MAXIMIZE
APPLICATION PERFORMANCE
BY DANIEL FIELDS
OVERVIEW
 What is V8?
 Dynamically Typed vs Statically Typed
 The V8 Solution
 Some Practical Measures
OVERVIEW
 What is V8?
 Dynamically Typed vs Statically Typed
 The V8 Solution
 Some Practical Measures
WHAT IS V8?
Core Modules
OVERVIEW
 What is V8?
 Dynamically Typed vs Statically Typed
 The V8 Solution
 Some Practical Measures
DYNAMICALLY TYPED VS STATICALLY TYPED
const point = {
x: 42,
y: 24
};
=
=const tuples =
[42, ’24’];
const point = {};
point.x = 42;
point.y = 24;
const tuples = [];
tuples[0] = 42;
tuples[1] = ’24’;
DYNAMICALLY TYPED VS STATICALLY TYPED
const point = {
x: 42,
y: 24
};
≠
≠const tuples =
[42, ’24’];
const point = {};
point.x = 42;
point.y = 24;
const tuples = [];
tuples[0] = 42;
tuples[1] = ’24’;
DYNAMICALLY TYPED VS STATICALLY TYPED
Statically Typed
 Checks type annotations at compile time
 Enforces type constraints
Dynamically Typed
 Checks type annotations at runtime
 No type constraints
DYNAMICALLY TYPED VS STATICALLY TYPED
Statically Typed
 Checks type annotations at compile time
 Enforces type constraints
Pros
 Compile-time optimizations
Cons
 Rigid / requires more boilerplate
Dynamically Typed
 Checks type annotations at runtime
 No type constraints
Pros
 Very flexible / minimizes boilerplate
Cons
 No compile-time optimizations
DYNAMICALLY TYPED VS STATICALLY TYPED
let myVar;
myVar = 42;
myVar = ’42’;
myVar = { oh: ‘hai’ };
myVar = [ ‘make it stop’ ];
myVar = () => {
return Date.now;
};
myVar.meta = ”I’m so Meta Even This Acronym”;
myVar = myVar();
WHAT’S GOING ON?
let myVar;
myVar = 42;
myVar = ’42’;
myVar = { oh: ‘hai’ };
myVar = [ ‘make it stop’ ];
myVar = () => {
return Date.now;
};
myVar.meta = ”I’m so Meta Even This Acronym”;
myVar = myVar();
WTF?
OVERVIEW
 What is V8?
 Dynamically Typed vs Statically Typed
 The V8 Solution
 Some Practical Measures
THE V8 SOLUTION
Build Type
Annotations
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
Optimize
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
Optimize
Hidden Classes Inline Caching TurboFan JIT
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
Optimize
Hidden Classes Inline Caching TurboFan JIT
THE V8 SOLUTION - HIDDEN CLASSES
let point = {
x: 42,
y: 24
};
Name Offset
x 0
y 1
Point_0
THE V8 SOLUTION - HIDDEN CLASSES
let point = {
x: 42,
y: 24
};
Name Offset
x 0
y 1
Point_0
Values Array
42
24
THE V8 SOLUTION - HIDDEN CLASSES
let point = {
x: 42,
y: 24
};
point.z = 66;
Name Offset
x 0
y 1
Point_0
Values Array
42
24
THE V8 SOLUTION - HIDDEN CLASSES
let point = {
x: 42,
y: 24
};
point.z = 66;
Name Offset
x 0
y 1
Point_0
Values Array
42
24
Name Offset
x 0
y 1
z 2
Point_1
Values Array
42
24
66
THE V8 SOLUTION - HIDDEN CLASSES
function(que) {
let point = (que)
? { x: 42, y: 24 }
: { y: 42, x: 24 };
return point;
};
Name Offset
x 0
y 1
Point_0
Values Array
42
24
Name Offset
y 0
x 1
Point_1
Values Array
24
42
THE V8 SOLUTION - HIDDEN CLASSES
function(que) {
let point = (que)
? { x: 42, y: 24 }
: { x: 42, y: 24 };
return point;
};
Name Offset
x 0
y 1
Point_0
Values Array
42
24
Values Array
24
42
THE V8 SOLUTION - HIDDEN CLASSES
function(que) {
let point = (que)
? { x: 42, y: 24, z: 66 }
: { x: 24, y: 42, z: 66 };
return point;
};
Name Offset
x 0
y 1
z 2
Point_0
Values Array
42
24
66
Values Array
24
42
66
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
Optimize
Hidden Classes Inline Caching TurboFan JIT
THE V8 SOLUTION - INLINE CACHING
Variable
(A)
Hidden Class
(string)
Inline
Cache
THE V8 SOLUTION - INLINE CACHING
Variable
(A)
Hidden Class
(string)
Variable A
string
shortcut
Inline
Cache
THE V8 SOLUTION - INLINE CACHING
Variable
(A)
Hidden Class
(string)
Variable A
string
shortcut
Hidden Class
(numeric)
Inline
Cache
THE V8 SOLUTION - INLINE CACHING
Variable
(A)
Hidden Class
(string)
Variable A
string
shortcut
Hidden Class
(numeric)
Variable A
numeric
shortcut
Inline
Cache
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
Shortcut to numeric ”a”
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
let value1 = square(3);
let value2 = square(4);
let value3 = square(5);
Shortcut to numeric ”a”
Monomorphic
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
let value1 = square(‘2’);
Shortcut to numeric ”a”
Shortcut to string ”a”
Polymorphic
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
let value1 = square(‘2’);
let value2 = square(Date.now);
let value3 = square({
valueOf: () => { return 2; }
});
Shortcut to numeric ”a”
Shortcut to A_0 object ”a”
Shortcut to string”a”
Shortcut to Date”a”
Megamorphic!
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
let value0 = square(2);
let value1 = square(‘2’);
let value2 = square(Date.now);
let value3 = square({
valueOf: () => { return 2; }
});
Shortcut to numeric ”a”
Shortcut to A_0 object ”a”
Shortcut to string”a”
Shortcut to Date”a”
Megamorphic! Megamorphic global hashtable
THE V8 SOLUTION - INLINE CACHING
function square(a) {
return a * a;
}
const value0 = square(2);
const value1 = square(parseInt(’3’));
Monomorphic!
THE V8 SOLUTION
Build Type
Annotations
Cache Access
Strategies
Optimize
Hidden Classes Inline Caching TurboFan JIT
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
 Functionally similar to the “full compiler”
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
 Functionally similar to the “full compiler”
 Builds a graph of internal representation (IR) of code
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
 Functionally similar to the “full compiler”
 Builds a graph of internal representation (IR) of code
 Optimization engine applies various rules as the
IR is constructed, and un-optimized machine code is
replaced with optimized machine code
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
const a = 2;
const b = 2;
const sum = a + b;
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
const a = 2;
const b = 2;
const sum = a + b;
mov eax, a
mov ebx, b
call RuntimeAdd
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
const a = 2;
const b = 2;
const sum = a + b;
mov eax, a
mov ebx, b
add eax, ebx
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
const a = 2;
const b = 2;
const sum = a + b;
mov eax, a
mov ebx, b
add eax, ebx
Canonicalization, architecture-specific optimizations, dead code removal, global
value numbering, loop invariant code motion, redundant bounds check elimination,
etc.
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
 Some code cannot be optimized...
THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
 Some code cannot be optimized...
 Reassigning a defined parameter while mentioning arguments
 Object literals that contain __proto__, or get or set declarations
 Functions that use debugger, eval(), or with statements
 for-in statements where they key is not a local variable
 for-in statements on arrays
 Infinite loops with deep logic exit conditions
OVERVIEW
 What is V8?
 Dynamically Typed vs Statically Typed
 The V8 Solution
 Some Practical Measures
SOME PRACTICAL MEASURES
Define variables with as much information as
possible...
Do:
const point = {
x: 42,
y: 24
};
Don’t:
const point = {}
point.x = 42;
point.y = 24;
SOME PRACTICAL MEASURES
Perform your own coercion on variables before passing to
functions...
Do:
const a = ’24’;
square(parseInt(a));
Don’t:
const a = ’24’;
square(a);
SOME PRACTICAL MEASURES
Don’t reassign a defined parameter while mentioning arguments...
Do:
function argsReassign(a, _b) {
let b = _b;
if (arguments.length < 2) b = 5;
}
Don’t:
function argsReassign(a, b) {
if (arguments.length < 2) b = 5;
}
SOME PRACTICAL MEASURES
Don’t use __proto__, get, or set in object literals...
Don’t:
function someUnoptimizableFunction() {
return {
__proto__: 42,
get a() { return ‘a’; }
set a(val) { this._a = val; }
};
}
SOME PRACTICAL MEASURES
Don’t use debugger...
Don’t:
function someUnoptimizableFunction() {
if (process.env.NODE_ENV === ‘develop’) {
debugger;
}
}
SOME PRACTICAL MEASURES
Don’t use with...
Don’t:
function someUnoptimizableFunction(hello) {
with (hello) {
console.log(world);
}
}
SOME PRACTICAL MEASURES
Don’t use eval...
Don’t:
function someUnoptimizableFunction(script) {
return eval(script);
}
SOME PRACTICAL MEASURES
Don’t use for-in statements on arrays...
Do:
function optimizable() {
const obj =[1, 1, 2, 3, 5, 8];
for (let i = 0; i < obj.length; i++);
}
Don’t:
function unoptimizable() {
const obj =[1, 1, 2, 3, 5, 8];
for (const item in obj);
}
SOME PRACTICAL MEASURES
Don’t create infinite loops with deeply nested exit conditions...
Do:
function optimizable() {
while (someExitCondition()) {
// do stuff
}
}
Don’t:
function unoptimizable() {
while (true) {
if (someExitCondition()) {
break;
}
}
}
TURBOFAN IS RAPIDLY EVOLVING
 The switch from CrankShaft to TurboFan represents a complete redesign of the optimizing compiler.
 TurboFan GREATLY simplified the code.
 Consequently, the project is seeing more contributors.
 Compiler bailouts are being fixed.
 This presentation may be out of date by the time you read it.
 Follow the V8 project on GitHub to keep up-to-date on new features
https://github.com/v8/v8
SOME PRACTICAL MEASURES
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of
all evil. Yet we should not pass up our opportunities in that critical 3%”
“In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal
and I believe the same viewpoint should prevail in software engineering”
– Donald Knuth
THE END
Thank You!
Dan Fields
https://www.linkedin.com/in/danielsfields
https://github.com/dsfields
@danielsfields

More Related Content

What's hot

Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your code
vmandrychenko
 
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
Förderverein Technische Fakultät
 
MuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for CMuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for C
Susumu Tokumoto
 
Firefox content
Firefox contentFirefox content
Firefox content
Ubald Agi
 

What's hot (19)

Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your code
 
Kpi driven-java-development-fn conf
Kpi driven-java-development-fn confKpi driven-java-development-fn conf
Kpi driven-java-development-fn conf
 
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
Theorie, Praxis und Perspektiven der operationsbasierten formalen Schaltungsv...
 
Testing and Validating End User Programmed Calculated Fields
Testing and Validating End User Programmed Calculated FieldsTesting and Validating End User Programmed Calculated Fields
Testing and Validating End User Programmed Calculated Fields
 
MuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for CMuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for C
 
Digital System Design Lab Report - VHDL ECE
Digital System Design Lab Report - VHDL ECEDigital System Design Lab Report - VHDL ECE
Digital System Design Lab Report - VHDL ECE
 
Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»
 
Functional Design Explained (David Sankel CppCon 2015)
Functional Design Explained (David Sankel CppCon 2015)Functional Design Explained (David Sankel CppCon 2015)
Functional Design Explained (David Sankel CppCon 2015)
 
PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...
 
Clean up your code with C#6
Clean up your code with C#6Clean up your code with C#6
Clean up your code with C#6
 
Accelerated Mac OS X Core Dump Analysis training public slides
Accelerated Mac OS X Core Dump Analysis training public slidesAccelerated Mac OS X Core Dump Analysis training public slides
Accelerated Mac OS X Core Dump Analysis training public slides
 
Refactoring Example
Refactoring ExampleRefactoring Example
Refactoring Example
 
Digital system design practical file
Digital system design practical fileDigital system design practical file
Digital system design practical file
 
The Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDEThe Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDE
 
C Prog - Array
C Prog - ArrayC Prog - Array
C Prog - Array
 
JavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx VersionJavaFX Your Way - Devoxx Version
JavaFX Your Way - Devoxx Version
 
Repair dagstuhl jan2017
Repair dagstuhl jan2017Repair dagstuhl jan2017
Repair dagstuhl jan2017
 
Srinivas Reddy Amedapu C and Data Structures JNTUH Hyderabad
Srinivas Reddy Amedapu C and Data Structures JNTUH HyderabadSrinivas Reddy Amedapu C and Data Structures JNTUH Hyderabad
Srinivas Reddy Amedapu C and Data Structures JNTUH Hyderabad
 
Firefox content
Firefox contentFirefox content
Firefox content
 

Similar to Understanding the v8 runtime to maximize application performance

Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, TuningJava 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Carol McDonald
 
Two-StageCreation
Two-StageCreationTwo-StageCreation
Two-StageCreation
gillygize
 
NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
tcaesvk
 
Verilog for synthesis - combinational rev a.pdf
Verilog for synthesis - combinational rev a.pdfVerilog for synthesis - combinational rev a.pdf
Verilog for synthesis - combinational rev a.pdf
AzeemMohammedAbdul
 
Bdd for-dso-1227123516572504-8
Bdd for-dso-1227123516572504-8Bdd for-dso-1227123516572504-8
Bdd for-dso-1227123516572504-8
Frédéric Delorme
 

Similar to Understanding the v8 runtime to maximize application performance (20)

ruby on rails pitfalls
ruby on rails pitfallsruby on rails pitfalls
ruby on rails pitfalls
 
JavaScriptCore's DFG JIT (JSConf EU 2012)
JavaScriptCore's DFG JIT (JSConf EU 2012)JavaScriptCore's DFG JIT (JSConf EU 2012)
JavaScriptCore's DFG JIT (JSConf EU 2012)
 
Boost delivery stream with code discipline engineering
Boost delivery stream with code discipline engineeringBoost delivery stream with code discipline engineering
Boost delivery stream with code discipline engineering
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, TuningJava 5 6 Generics, Concurrency, Garbage Collection, Tuning
Java 5 6 Generics, Concurrency, Garbage Collection, Tuning
 
Two-StageCreation
Two-StageCreationTwo-StageCreation
Two-StageCreation
 
TDD, BDD and mocks
TDD, BDD and mocksTDD, BDD and mocks
TDD, BDD and mocks
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#NDC 2011, C++ 프로그래머를 위한 C#
NDC 2011, C++ 프로그래머를 위한 C#
 
Kotlin Backend Development 6 Yrs Recap. The Good, the Bad and the Ugly
Kotlin Backend Development 6 Yrs Recap. The Good, the Bad and the UglyKotlin Backend Development 6 Yrs Recap. The Good, the Bad and the Ugly
Kotlin Backend Development 6 Yrs Recap. The Good, the Bad and the Ugly
 
Verilog for synthesis - combinational rev a.pdf
Verilog for synthesis - combinational rev a.pdfVerilog for synthesis - combinational rev a.pdf
Verilog for synthesis - combinational rev a.pdf
 
How to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJITHow to add an optimization for C# to RyuJIT
How to add an optimization for C# to RyuJIT
 
Bdd for-dso-1227123516572504-8
Bdd for-dso-1227123516572504-8Bdd for-dso-1227123516572504-8
Bdd for-dso-1227123516572504-8
 
Metaprogramming, Metaobject Protocols, Gradual Type Checks: Optimizing the "U...
Metaprogramming, Metaobject Protocols, Gradual Type Checks: Optimizing the "U...Metaprogramming, Metaobject Protocols, Gradual Type Checks: Optimizing the "U...
Metaprogramming, Metaobject Protocols, Gradual Type Checks: Optimizing the "U...
 
ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine
 
Core2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdfCore2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdf
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
 
Counter Wars (JEEConf 2016)
Counter Wars (JEEConf 2016)Counter Wars (JEEConf 2016)
Counter Wars (JEEConf 2016)
 
Vectorization in ATLAS
Vectorization in ATLASVectorization in ATLAS
Vectorization in ATLAS
 

Recently uploaded

Recently uploaded (20)

What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration Tooling
 
BusinessGPT - Security and Governance for Generative AI
BusinessGPT  - Security and Governance for Generative AIBusinessGPT  - Security and Governance for Generative AI
BusinessGPT - Security and Governance for Generative AI
 
WSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid Environments
 
WSO2CON 2024 - Software Engineering for Digital Businesses
WSO2CON 2024 - Software Engineering for Digital BusinessesWSO2CON 2024 - Software Engineering for Digital Businesses
WSO2CON 2024 - Software Engineering for Digital Businesses
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2CON 2024 - Building a Digital Government in Uganda
WSO2CON 2024 - Building a Digital Government in UgandaWSO2CON 2024 - Building a Digital Government in Uganda
WSO2CON 2024 - Building a Digital Government in Uganda
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2CON 2024 - Lessons from the Field: Legacy Platforms – It's Time to Let Go...
WSO2CON 2024 - Lessons from the Field: Legacy Platforms – It's Time to Let Go...WSO2CON 2024 - Lessons from the Field: Legacy Platforms – It's Time to Let Go...
WSO2CON 2024 - Lessons from the Field: Legacy Platforms – It's Time to Let Go...
 
WSO2CON 2024 - OSU & WSO2: A Decade Journey in Integration & Innovation
WSO2CON 2024 - OSU & WSO2: A Decade Journey in Integration & InnovationWSO2CON 2024 - OSU & WSO2: A Decade Journey in Integration & Innovation
WSO2CON 2024 - OSU & WSO2: A Decade Journey in Integration & Innovation
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
 
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
 
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public AdministrationWSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
 
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
 
[GeeCON2024] How I learned to stop worrying and love the dark silicon apocalypse
[GeeCON2024] How I learned to stop worrying and love the dark silicon apocalypse[GeeCON2024] How I learned to stop worrying and love the dark silicon apocalypse
[GeeCON2024] How I learned to stop worrying and love the dark silicon apocalypse
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdfAzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
 

Understanding the v8 runtime to maximize application performance

  • 1. UNDERSTANDING THE V8 RUNTIME TO MAXIMIZE APPLICATION PERFORMANCE BY DANIEL FIELDS
  • 2. OVERVIEW  What is V8?  Dynamically Typed vs Statically Typed  The V8 Solution  Some Practical Measures
  • 3. OVERVIEW  What is V8?  Dynamically Typed vs Statically Typed  The V8 Solution  Some Practical Measures
  • 5. OVERVIEW  What is V8?  Dynamically Typed vs Statically Typed  The V8 Solution  Some Practical Measures
  • 6. DYNAMICALLY TYPED VS STATICALLY TYPED const point = { x: 42, y: 24 }; = =const tuples = [42, ’24’]; const point = {}; point.x = 42; point.y = 24; const tuples = []; tuples[0] = 42; tuples[1] = ’24’;
  • 7. DYNAMICALLY TYPED VS STATICALLY TYPED const point = { x: 42, y: 24 }; ≠ ≠const tuples = [42, ’24’]; const point = {}; point.x = 42; point.y = 24; const tuples = []; tuples[0] = 42; tuples[1] = ’24’;
  • 8. DYNAMICALLY TYPED VS STATICALLY TYPED Statically Typed  Checks type annotations at compile time  Enforces type constraints Dynamically Typed  Checks type annotations at runtime  No type constraints
  • 9. DYNAMICALLY TYPED VS STATICALLY TYPED Statically Typed  Checks type annotations at compile time  Enforces type constraints Pros  Compile-time optimizations Cons  Rigid / requires more boilerplate Dynamically Typed  Checks type annotations at runtime  No type constraints Pros  Very flexible / minimizes boilerplate Cons  No compile-time optimizations
  • 10. DYNAMICALLY TYPED VS STATICALLY TYPED let myVar; myVar = 42; myVar = ’42’; myVar = { oh: ‘hai’ }; myVar = [ ‘make it stop’ ]; myVar = () => { return Date.now; }; myVar.meta = ”I’m so Meta Even This Acronym”; myVar = myVar();
  • 11. WHAT’S GOING ON? let myVar; myVar = 42; myVar = ’42’; myVar = { oh: ‘hai’ }; myVar = [ ‘make it stop’ ]; myVar = () => { return Date.now; }; myVar.meta = ”I’m so Meta Even This Acronym”; myVar = myVar(); WTF?
  • 12. OVERVIEW  What is V8?  Dynamically Typed vs Statically Typed  The V8 Solution  Some Practical Measures
  • 13. THE V8 SOLUTION Build Type Annotations
  • 14. THE V8 SOLUTION Build Type Annotations Cache Access Strategies
  • 15. THE V8 SOLUTION Build Type Annotations Cache Access Strategies Optimize
  • 16. THE V8 SOLUTION Build Type Annotations Cache Access Strategies Optimize Hidden Classes Inline Caching TurboFan JIT
  • 17. THE V8 SOLUTION Build Type Annotations Cache Access Strategies Optimize Hidden Classes Inline Caching TurboFan JIT
  • 18. THE V8 SOLUTION - HIDDEN CLASSES let point = { x: 42, y: 24 }; Name Offset x 0 y 1 Point_0
  • 19. THE V8 SOLUTION - HIDDEN CLASSES let point = { x: 42, y: 24 }; Name Offset x 0 y 1 Point_0 Values Array 42 24
  • 20. THE V8 SOLUTION - HIDDEN CLASSES let point = { x: 42, y: 24 }; point.z = 66; Name Offset x 0 y 1 Point_0 Values Array 42 24
  • 21. THE V8 SOLUTION - HIDDEN CLASSES let point = { x: 42, y: 24 }; point.z = 66; Name Offset x 0 y 1 Point_0 Values Array 42 24 Name Offset x 0 y 1 z 2 Point_1 Values Array 42 24 66
  • 22. THE V8 SOLUTION - HIDDEN CLASSES function(que) { let point = (que) ? { x: 42, y: 24 } : { y: 42, x: 24 }; return point; }; Name Offset x 0 y 1 Point_0 Values Array 42 24 Name Offset y 0 x 1 Point_1 Values Array 24 42
  • 23. THE V8 SOLUTION - HIDDEN CLASSES function(que) { let point = (que) ? { x: 42, y: 24 } : { x: 42, y: 24 }; return point; }; Name Offset x 0 y 1 Point_0 Values Array 42 24 Values Array 24 42
  • 24. THE V8 SOLUTION - HIDDEN CLASSES function(que) { let point = (que) ? { x: 42, y: 24, z: 66 } : { x: 24, y: 42, z: 66 }; return point; }; Name Offset x 0 y 1 z 2 Point_0 Values Array 42 24 66 Values Array 24 42 66
  • 25. THE V8 SOLUTION Build Type Annotations Cache Access Strategies Optimize Hidden Classes Inline Caching TurboFan JIT
  • 26. THE V8 SOLUTION - INLINE CACHING Variable (A) Hidden Class (string) Inline Cache
  • 27. THE V8 SOLUTION - INLINE CACHING Variable (A) Hidden Class (string) Variable A string shortcut Inline Cache
  • 28. THE V8 SOLUTION - INLINE CACHING Variable (A) Hidden Class (string) Variable A string shortcut Hidden Class (numeric) Inline Cache
  • 29. THE V8 SOLUTION - INLINE CACHING Variable (A) Hidden Class (string) Variable A string shortcut Hidden Class (numeric) Variable A numeric shortcut Inline Cache
  • 30. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2);
  • 31. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2); Shortcut to numeric ”a”
  • 32. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2); let value1 = square(3); let value2 = square(4); let value3 = square(5); Shortcut to numeric ”a” Monomorphic
  • 33. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2); let value1 = square(‘2’); Shortcut to numeric ”a” Shortcut to string ”a” Polymorphic
  • 34. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2); let value1 = square(‘2’); let value2 = square(Date.now); let value3 = square({ valueOf: () => { return 2; } }); Shortcut to numeric ”a” Shortcut to A_0 object ”a” Shortcut to string”a” Shortcut to Date”a” Megamorphic!
  • 35. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } let value0 = square(2); let value1 = square(‘2’); let value2 = square(Date.now); let value3 = square({ valueOf: () => { return 2; } }); Shortcut to numeric ”a” Shortcut to A_0 object ”a” Shortcut to string”a” Shortcut to Date”a” Megamorphic! Megamorphic global hashtable
  • 36. THE V8 SOLUTION - INLINE CACHING function square(a) { return a * a; } const value0 = square(2); const value1 = square(parseInt(’3’)); Monomorphic!
  • 37. THE V8 SOLUTION Build Type Annotations Cache Access Strategies Optimize Hidden Classes Inline Caching TurboFan JIT
  • 38. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)
  • 39. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)  Functionally similar to the “full compiler”
  • 40. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)  Functionally similar to the “full compiler”  Builds a graph of internal representation (IR) of code
  • 41. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)  Functionally similar to the “full compiler”  Builds a graph of internal representation (IR) of code  Optimization engine applies various rules as the IR is constructed, and un-optimized machine code is replaced with optimized machine code
  • 42. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN) const a = 2; const b = 2; const sum = a + b;
  • 43. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN) const a = 2; const b = 2; const sum = a + b; mov eax, a mov ebx, b call RuntimeAdd
  • 44. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN) const a = 2; const b = 2; const sum = a + b; mov eax, a mov ebx, b add eax, ebx
  • 45. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN) const a = 2; const b = 2; const sum = a + b; mov eax, a mov ebx, b add eax, ebx Canonicalization, architecture-specific optimizations, dead code removal, global value numbering, loop invariant code motion, redundant bounds check elimination, etc.
  • 46. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)  Some code cannot be optimized...
  • 47. THE V8 SOLUTION - THE OPTIMIZING COMPILER (TURBOFAN)  Some code cannot be optimized...  Reassigning a defined parameter while mentioning arguments  Object literals that contain __proto__, or get or set declarations  Functions that use debugger, eval(), or with statements  for-in statements where they key is not a local variable  for-in statements on arrays  Infinite loops with deep logic exit conditions
  • 48. OVERVIEW  What is V8?  Dynamically Typed vs Statically Typed  The V8 Solution  Some Practical Measures
  • 49. SOME PRACTICAL MEASURES Define variables with as much information as possible... Do: const point = { x: 42, y: 24 }; Don’t: const point = {} point.x = 42; point.y = 24;
  • 50. SOME PRACTICAL MEASURES Perform your own coercion on variables before passing to functions... Do: const a = ’24’; square(parseInt(a)); Don’t: const a = ’24’; square(a);
  • 51. SOME PRACTICAL MEASURES Don’t reassign a defined parameter while mentioning arguments... Do: function argsReassign(a, _b) { let b = _b; if (arguments.length < 2) b = 5; } Don’t: function argsReassign(a, b) { if (arguments.length < 2) b = 5; }
  • 52. SOME PRACTICAL MEASURES Don’t use __proto__, get, or set in object literals... Don’t: function someUnoptimizableFunction() { return { __proto__: 42, get a() { return ‘a’; } set a(val) { this._a = val; } }; }
  • 53. SOME PRACTICAL MEASURES Don’t use debugger... Don’t: function someUnoptimizableFunction() { if (process.env.NODE_ENV === ‘develop’) { debugger; } }
  • 54. SOME PRACTICAL MEASURES Don’t use with... Don’t: function someUnoptimizableFunction(hello) { with (hello) { console.log(world); } }
  • 55. SOME PRACTICAL MEASURES Don’t use eval... Don’t: function someUnoptimizableFunction(script) { return eval(script); }
  • 56. SOME PRACTICAL MEASURES Don’t use for-in statements on arrays... Do: function optimizable() { const obj =[1, 1, 2, 3, 5, 8]; for (let i = 0; i < obj.length; i++); } Don’t: function unoptimizable() { const obj =[1, 1, 2, 3, 5, 8]; for (const item in obj); }
  • 57. SOME PRACTICAL MEASURES Don’t create infinite loops with deeply nested exit conditions... Do: function optimizable() { while (someExitCondition()) { // do stuff } } Don’t: function unoptimizable() { while (true) { if (someExitCondition()) { break; } } }
  • 58. TURBOFAN IS RAPIDLY EVOLVING  The switch from CrankShaft to TurboFan represents a complete redesign of the optimizing compiler.  TurboFan GREATLY simplified the code.  Consequently, the project is seeing more contributors.  Compiler bailouts are being fixed.  This presentation may be out of date by the time you read it.  Follow the V8 project on GitHub to keep up-to-date on new features https://github.com/v8/v8
  • 59. SOME PRACTICAL MEASURES “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%” “In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal and I believe the same viewpoint should prevail in software engineering” – Donald Knuth
  • 60. THE END Thank You! Dan Fields https://www.linkedin.com/in/danielsfields https://github.com/dsfields @danielsfields

Editor's Notes

  1. This talk is primarily based on how the V8 runtime handles JavaScript’s dynamic type system. The content is framed to compare dynamically typed languages against statically typed languages. How V8 attempts to provide the similar optimizations found in statically typed language compilers. And, finally, some simple things you can do to take advantage of V8’s optimizer.
  2. V8 is the JavaScript engine built into the Chrome web browser. It is also the default JavaScript runtime used by Node.js. V8 is a JavaScript parser, compiler, and runtime all in one.
  3. JavaScript is a dynamic and interpreted language. As we see, this allows us to write code that, from our perspective, is conceptually the same, and only syntactically different. But what about from V8’s perspective?
  4. JavaScript is a dynamic and interpreted language. As we see, this allows us to write code that, from our perspective, is conceptually the same, and only syntactically different. But what about from V8’s perspective?
  5. The differences between static and dynamic languages are pretty straight forward. They can be summed up by the manner in which they handle type annotations. Type annotations are meta data about data types, and serve as hints about how the runtime should handle a variable in a particular context.
  6. These differences come with tradeoffs. In a statically typed language, the compiler knows exactly how to handle a particular variable. The compiler can then emit machine code that knows exactly how to allocate and address variables in memory, and it can more easily take advantage of architecture-specific optimizations. The trade-off here is, you’ll inevitably have to write more code to handle various type differences for different situations. In other words, more boilerplate. Since JavaScript is dynamic, we don’t have the problem. However, no compile-time optimizations, which can make things slower.
  7. To illustrate this point, consider this example. myVar can basically be anything. And V8 will handle it.
  8. As a consequence, it becomes quite difficult for a compiler to make assumptions about a piece of code is, at a low level, going run. JavaScript is syntactically a fairly lean language, but the reality is, the language is remarkably complex. This makes performing even simple operations surprisingly difficult.
  9. To understand why, we’ll need to dive a bit deeper into what V8 is doing under the hood.
  10. Back to the notion of type annotations for a moment. Even though V8 can’t know what the type of a variable is at compile time, it still needs a way to know about a type. So, it will attempt to build type annotations as it executes.
  11. Now, V8 can utilize this information to determine an access strategy for in-memory data to perform a specific operation. No more complex decision trees.
  12. Finally, we are able to run an optimizing compiler on on our code.
  13. Along the way, V8 uses various constructs designed to efficiently solve their respective problem. So lets dive into the design of these components, and see how they can influence the patterns and practices we should be following when structuring code.
  14. As mentioned, hidden classes solve the type annotation problem. On the left here, we have a small bit of code where we’re declaring an object with two properties, x and y. On the right, we have table that shows us what the hidden class definition of the type of our variable point looks like. The hidden class table defines the names of our object’s properties, and an offset value; which is a reference to the order that property is defined on the hidden class.
  15. Our point variable is an instance of our hidden class Point_0. And instance values are then stored in an array, where each value is mapped back to their respective property based on their offset in the array. All very simple. Now the caveat: hidden classes are immutable.
  16. But a variable’s type is dynamic. So, what happens when the type changes?
  17. The answer is, a new hidden class is created. So, you can start to see how the behavior of hidden classes dictate how we should structure our code.
  18. Even the order in which we define our object properties can result in new hidden classes being created. The consequences of having multiple hidden classes can increase memory consumptions. But even more importantly, the different code paths can now no longer utilize the same optimized code. We’ll get into what exactly that means in a moment.
  19. So, make sure you declare your variables and objects consistently.
  20. And include as much as you can at the time an object instance is declared. We now have the type annotation information we need to figure out how to efficiently load data when performing an operation.
  21. So, now that we have our type annotations, the runtime needs a way to reference them in memory. Enter inline caching.
  22. The easiest way to think of an inline cache is a shortcut to finding a variable value in memory. Here we have variable A, which is of a hidden class of type string.
  23. This information allows us to reference a shortcut to specific spot in memory.
  24. So, what happens if variable A isn’t referencing its string hidden class anymore? Instead it’s referencing its numeric valued hidden class. Simple, we end up with a cache miss.
  25. And a new entry in the cache is created.
  26. And we’re invoking our function, and passing in the numeric value 2. The runtime either gets or creates an inline cache entry for numeric “a” that allows us to reference the correct value in memory so we can complete our multiplication operation.
  27. Now lets say we continue calling our function more or less the same way. Our function only needs one inline cache entry, and has a single, unchanged path of execution. We call this a monomorphic function.
  28. Lets change the scenario a bit. In this case, we’re passing in a string. So, we have a cache miss, and we create a new shortcut entry in the inline cache. Our code now has multiple inline cache entries, and, as a result, a logical path of execution that can change depending on the hidden class of our “a” parameter. Our function is now polymorphic.
  29. And we can continue on adding shortcut entries into our inline cache, something interesting happens. V8 has a hard maximum limit of 3 entries in the inline cache. This is a safeguard against ensuring all of our many inline caches don’t grow indefinitely. We now have a megamorphic function. This is not good.
  30. Because instead of using an inline cache, we now must use a global hashtable to store or shortcuts. In addition to being considerably slower than an inline cache lookups, the hashtable is a fixed size. Entries follow a LRU strategy for cache ejection. That means our program can be further slowed down due to frequent cache misses.
  31. Plan accordingly. Create separate functions to accommodate the different hidden classes that result in your code. The reason for this, is because of the final component we need to talk about.
  32. Now that V8 has type information and access strategies, the code can now be optimized.
  33. I don’t want to dive too deep into the design of TurboFan, as that could its own series of talks. And it’s not necessary for understanding how to take advantage of TurboFan’s code optimizations. So, lets just walk through a high-level description, and see an example.
  34. Functionally similar to the “full compiler” that generated the original machine code when I application first started running. The full compiler emits good machine code, but it can’t emit optimal code.
  35. You can think of
  36. You can think of
  37. Lets look at an example. Simple addition of two numeric variables.
  38. The full compiler may emit machine code that looks like this. What’s important to note here is the call to RuntimeAdd. This is V8’s internal function for summing to variables. It contains all of the coercion routines and inline cache look ups necessary to perform the operation on an unknown data type.
  39. Now lets assume that our code has remained monomorphic. Meaning, contextually, a and b have always been integers. And there is only one hidden class and inline cache for each. TurboFan can now make some assumptions and replace RuntimeAdd with the more optimal add instruction. And when I say more optimal, I mean possibly on the order of 100 times faster.
  40. There are many many more optimizations that TurboFan can perform on your code.
  41. A bailout is a situation where the optimizing compiler encounters a piece of code where it just says, “I don’t know what to do with this, so I’m not going to try.” That function will never become optimized.
  42. Functions that call un-optimizable functions cannot be optimized So, be careful, or you can end up with large swaths of your application that bailout of optimization entirely
  43. To understand why, we’ll need to dive a bit deeper into what V8 is doing under the hood.
  44. A couple of quotes from the master. The information presented here today is just another tool to be utilized while designing code. They cannot be used as hard-and-fast rules. Learn how to use them to create guidelines for how to compose code. Then learn how to break them when necessary.