230 likes | 559 Views
Kasper Lund October 4, 2008. V8: An Open-Source, High-Performance JavaScript Engine. Who Am I?. Kasper Lund, virtual machine addict 2000-2002: CLDC HI (Sun Microsystems) 2002-2006: Resilient (OOVM) 2006-2008: V8 (Google) Primary areas of interests: Dynamic programming languages
E N D
Kasper Lund October 4, 2008 V8: An Open-Source, High-Performance JavaScript Engine
Who Am I? • Kasper Lund, virtual machine addict • 2000-2002: CLDC HI (Sun Microsystems) • 2002-2006: Resilient (OOVM) • 2006-2008: V8 (Google) • Primary areas of interests: • Dynamic programming languages • Interpretation and dynamic code generation • Method dispatching
Challenges in Implementing JavaScript • A very dynamic programming language • Objects contain properties (ie, fields or methods) • Properties can be added or removed on the fly • Objects with completely different sets of properties can appear at the same property access site • Properties can be found in an object's prototype chain • Functions can be moved from one object to another
Motivation for a New JavaScript Engine • When starting the project: • Browsers had slow JavaScript implementations • They did not scale to large applications with many objects • They even had memory leaks when running web apps • The solution seemed simple: • Build a completely new engine from the ground up • Find a way to categorize objects into classes • Bring to bear techniques from static class-based languages
V8: A Scalable High-performance JS Engine • The goal was to raise the performance bar for JavaScript execution • Key design ideas in V8: • Hidden classes and hidden class transitions • Inline caching • Compilation to native code • Efficient memory-management system
Hidden Classes • In a static object-oriented language, a particular property is always found at a known offset in instances of a particular class • This is fast to access • In JavaScript, there are no classes • Objects appearing at a property access site may have a given property or not, found at various places in the object • This is slow - we need to speed it up • Hidden classes encode object layout and shared structure • Introduced behind-the-scenes • Enable class-based optimizations
Hidden Classes Example: function Point(x, y) { this.x = x; this.y = y; } var p = new Point(1, 2); var q = new Point(3, 4); Point p 1 2 Class0 Class1 Class2 Δx x:0 x:0 Δy y:1 Point q 3 4
How Dynamic is JavaScript at Runtime? • Introducing hidden classes allows us to measure how many different classes are seen at a site in the code • Roughly 90% of all access sites see objects with the same hidden class • Conclusion: • JavaScript is not as dynamic at runtime as you might think • We can use class-based object-oriented optimization techniques
Inline Caching • Each property access and function call is governed by an inline cache stub • Stubs are in one of three states: • Uninitialized: not executed yet • Monomorphic: only one class of objects seen • Megamorphic: more than one class of objects seen
Monomorphic Stub for Loading a Property 0xf7c0d32d: [Code]Instructions (size = 37)0xf7c0d344 0 8b442404 mov eax,[esp+0x4]0xf7c0d348 4 a801 test al,0x10xf7c0d34a 6 0f8414000000 jz 320xf7c0d350 12 8178ff81ab8ff7 cmp [eax+0xff],0xf78fab810xf7c0d357 19 0f8507000000 jnz 320xf7c0d35d 25 8b5803 mov ebx,[eax+0x3]0xf7c0d360 28 8b4307 mov eax,[ebx+0x7]0xf7c0d363 31 c3 ret0xf7c0d364 32 e993daffff jmp LoadIC_Miss
Megamorphic State • Lookup monomorphic stub in global lookup table • Hashed lookup based on address of class and hash code of the property name • Verify that the stub is suitable • Check that the stub type matches (load, store, call) • Check that the property name matches • Call the monomorphic stub • Class check automatically handled by the stub • Access is reasonably fast if all checks pass
Does It Really Matter? • Property load timings: • Monomorphic: 0.000249 usec • Megamorphic: 0.001390 usec (x5.5) • No inline caching: 0.008665 usec (x34.8) • Overall: • Inline caching speeds up benchmarks with a factor of ~11 • Faster property access is important to real apps too
Native-code Compiler • JavaScript source code is translated directly into machine code • There is no intermediate bytecode, because there is no interpreter • Functions are compiled JIT-style • Source code is parsed into syntax trees • A simple one-pass code generator is used • Only a few optimizations are applied • Code generators are implemented for x86 and ARM
Efficient Memory Management • Design goals: • Fast object allocation • Scalable object heap • Small garbage collection pause times • V8 uses a generational garbage collector
Object Heap Organization • Young Generation • New space: newly allocated objects, collected frequently • Old Generation • Code space: executable code objects • Old data space: objects with no pointers to the young gen. • Large object space: to avoid moving objects > 8KB • Hidden class space: requires special GC processing • Old pointer space: the rest of the old objects
Types of Garbage Collection • Scavenge collections are most frequent • Copying collector operating on the young generation • Allows single-pointer allocation • Pause times bounded by live data in young gen • Typical pause times: 1-2 ms • Mark-sweep collections for most full collections • Processes all spaces • Uses single-pointer and free-list allocation • Pause times bound by size of heap • Typical pause times: 30-50 ms • Mark-sweep-compact to eliminate fragmentation • Typical pause times: 50-150 ms
Where is the JavaScript Library? • All library functions are implemented in JavaScript • Examples: Array.prototype.join, String.prototype.replace • The benefits of not implementing it inside the engine: • Keeps the core engine cleaner • Easier to change and extend • Capitalizes on the performance of the JavaScript compiler • One drawback is startup time ~30 ms ... ... but there is a solution
Snapshotting of the Object Heap • V8 allows saving the initial heap in a snapshot • Serialized form is very fast to read • Includes pre-compiled code for JavaScript builtins • Integrated in the build system and embedded directly in V8 • With snapshots, the startup time is reduced to 4-8 ms
Open-Source • Open-source code and developed in the open • Permissive standard three clause BSD license • Developed in the open, all code reviews are public • See http://code.google.com/p/v8 • Interesting projects already using V8: • Chromium • V8R: Extensible JavaScript scripting shell • PyV8: Python running on top of V8
Benchmarks • Benchmarking a new scripting engine is tricky • V8 is optimized for property accesses and function calls • No existing benchmark suites really exercise that • But it’s important to a lot of real world web apps • The industry needs realistic and well-written benchmarks • No single existing benchmark suite covers all of JavaScript • How do we go about measuring performance today?
http://code.google.com/apis/v8/run.html • Richards • OS kernel simulation benchmark, originally written in BCPL by Martin Richards (539 lines) • DeltaBlue • One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (880 lines) • Crypto • Encryption and decryption benchmark based on code by Tom Wu (1689 lines) • RayTrace • Ray tracer benchmark based on code by Adam Burmister (3418 lines) • EarleyBoyer • Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (4682 lines)
Summary • V8 is a high-performance JavaScript engine • Runs well-structured applications really fast • Raises the performance bar for scripting languages • Scales to larger applications • V8 is open-source and developed in the open • Embed it in your own projects • Use it for scripting on your computer • Incorporate the best ideas into your own scripting engine