Hacking Webkit & Its JavaScript Engines

74
Thursday, November 3, 2011

description

WebKit, along with its JavaScript engines, is not a magical black box. We will show you the internal of various WebKit building blocks (10,000-foot overview) and how they work together. In particular, learn also the simple steps on how to experiment with WebKit with your own and leverage WebKit functionalities to find the performance problems, track the network issues, automate effective smoke tests, and implement per-pixel correctness tests. In addition, armed with a little extra knowledge about JavaScript engines, you will be ready to improve both the quality and performance of your JavaScript code.

Transcript of Hacking Webkit & Its JavaScript Engines

Page 1: Hacking Webkit & Its JavaScript Engines

Thursday, November 3, 2011

Page 2: Hacking Webkit & Its JavaScript Engines

forget to run

the tests

Typical Scenario

This is awesome!

Thursday, November 3, 2011

Page 3: Hacking Webkit & Its JavaScript Engines

Ariya Hidayat & Jarred NichollsSencha

Twitter: @ariyahidayat @jarrednicholls

HACKING WEBKIT & ITS JAVASCRIPT ENGINES

Thursday, November 3, 2011

Page 4: Hacking Webkit & Its JavaScript Engines

What is WebKit?

Thursday, November 3, 2011

Page 5: Hacking Webkit & Its JavaScript Engines

Browser at a High LevelUser Interface

Browser Engine

Graphics Stack

Data P

ersistence

Render Engine

JavaScript Engine

Networking I/O

Thursday, November 3, 2011

Page 6: Hacking Webkit & Its JavaScript Engines

Browser at a High LevelUser Interface

Browser Engine

Graphics Stack

Data P

ersistence

JavaScript Engine

Networking I/O

Render Engine

WebKit

Thursday, November 3, 2011

Page 7: Hacking Webkit & Its JavaScript Engines

≠Thursday, November 3, 2011

Page 8: Hacking Webkit & Its JavaScript Engines

⊂Thursday, November 3, 2011

Page 9: Hacking Webkit & Its JavaScript Engines

WebKit isEVERYWHERE!

Thursday, November 3, 2011

Page 10: Hacking Webkit & Its JavaScript Engines

Even in your living room!

Thursday, November 3, 2011

Page 11: Hacking Webkit & Its JavaScript Engines

How?

Thursday, November 3, 2011

Page 12: Hacking Webkit & Its JavaScript Engines

Client InterfaceThursday, November 3, 2011

Page 13: Hacking Webkit & Its JavaScript Engines

WebKit ComponentsRender Engine

WebCore

JavaScript Engine (JSC/V8)Client Interface

HTML

DOMCSS

SVG

Canvas

Thursday, November 3, 2011

Page 14: Hacking Webkit & Its JavaScript Engines

Port Abstraction

Client Interface

Networking I/O

GraphicsThemeEventsClipboard

Thread Geolocation Timer

API CallsEvents

Port(Chrome, Safari, etc.)

Thursday, November 3, 2011

Page 15: Hacking Webkit & Its JavaScript Engines

<input type=”number” />

WebKit Port

Paint me some spin

buttons, STAT!

I know how to do that!

Thursday, November 3, 2011

Page 16: Hacking Webkit & Its JavaScript Engines

<input type=”number” />

WebKit

right there

please, kthx

Thursday, November 3, 2011

Page 17: Hacking Webkit & Its JavaScript Engines

<input type=”number” />

Port

Piece of cake!

lookin’ sexy!

Thursday, November 3, 2011

Page 18: Hacking Webkit & Its JavaScript Engines

<input type=”number” />

Theme Interfacebool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);

Thursday, November 3, 2011

Page 19: Hacking Webkit & Its JavaScript Engines

<input type=”number” />

bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);

Theme Interface

Client Interface

Theme

RenderTheme->paint()

PortpaintInnerSpinButton

Thursday, November 3, 2011

Page 20: Hacking Webkit & Its JavaScript Engines

Command LineWebKit

Thursday, November 3, 2011

Page 21: Hacking Webkit & Its JavaScript Engines

Demo

Thursday, November 3, 2011

Page 22: Hacking Webkit & Its JavaScript Engines

How’d you do that!?

Thursday, November 3, 2011

Page 23: Hacking Webkit & Its JavaScript Engines

Headless WebKit

Thursday, November 3, 2011

Page 24: Hacking Webkit & Its JavaScript Engines

“Headless”

Thursday, November 3, 2011

Page 25: Hacking Webkit & Its JavaScript Engines

Display

Paint

Layout

Normal Browser

Thursday, November 3, 2011

Page 26: Hacking Webkit & Its JavaScript Engines

Display

Paint

Layout

Headless

X

Thursday, November 3, 2011

Page 27: Hacking Webkit & Its JavaScript Engines

What’s in it for me?

Thursday, November 3, 2011

Page 28: Hacking Webkit & Its JavaScript Engines

What’s in it for me?Automated “smoke” tests

Continuous integration

Pixel-perfect regression tests

Web scraping

...

Thursday, November 3, 2011

Page 29: Hacking Webkit & Its JavaScript Engines

Demo

Thursday, November 3, 2011

Page 30: Hacking Webkit & Its JavaScript Engines

JavaScript Optimizations & Best

Practices

Thursday, November 3, 2011

Page 31: Hacking Webkit & Its JavaScript Engines

Benchmark.jsRobust benchmarking libraryCreated by Mathias Bynens and John-David Dalton

Platform/Browser independent

Supports high-precision timers

http://benchmarkjs.com

Thursday, November 3, 2011

Page 32: Hacking Webkit & Its JavaScript Engines

var suite = new Benchmark.Suite;// add testssuite.add('RegExp#test', function() { /o/.test('Hello World!');}).add('String#indexOf', function() { 'Hello World!'.indexOf('o') > -1;}).add('String#match', function() { !!'Hello World!'.match(/o/);})// add listeners.on('complete', function() { console.log('Fastest is ' + this.filter('fastest').pluck('name'));})// run.run();

Thursday, November 3, 2011

Page 33: Hacking Webkit & Its JavaScript Engines

jsperf.comOnline JavaScript benchmarking toolCreated by Mathias Bynens

Powered by Benchmark.js

Integrated with Browserscopehttp://www.browserscope.org/

Easy benchmark suite setup / teardown

http://jsperf.com

Thursday, November 3, 2011

Page 34: Hacking Webkit & Its JavaScript Engines

Best PracticesBatching DOM Operations

Reuse & Recycle DOM

Cache Variables

Optimal Enumeration

Dirty Math Hack

Thursday, November 3, 2011

Page 35: Hacking Webkit & Its JavaScript Engines

Batch DOM Operations

Thursday, November 3, 2011

Page 36: Hacking Webkit & Its JavaScript Engines

<span id="test"></span>var span = document.getElementById('test');

setup

Thursday, November 3, 2011

Page 37: Hacking Webkit & Its JavaScript Engines

span.innerHTML = '';for (var i = 0; i < 10; i++) { span.innerHTML += 'Line #' + (i+1) + '<br />';}

span.innerHTML = '';var buffer = '';for (var i = 0; i < 10; i++) { buffer += 'Line #' + (i+1) + '<br />';}span.innerHTML = buffer;

multiple ops

single op

Thursday, November 3, 2011

Page 38: Hacking Webkit & Its JavaScript Engines

span.innerHTML = '';for (var i = 0; i < 10; i++) { span.innerHTML += 'Line #' + (i+1) + '<br />';}

span.innerHTML = '';var buffer = '';for (var i = 0; i < 10; i++) { buffer += 'Line #' + (i+1) + '<br />';}span.innerHTML = buffer;

multiple ops

single op

fast

slow

Thursday, November 3, 2011

Page 39: Hacking Webkit & Its JavaScript Engines

Batch DOM Operations

http://jsperf.com/batch-dom-operations

Thursday, November 3, 2011

Page 40: Hacking Webkit & Its JavaScript Engines

Reuse & Recycle

Thursday, November 3, 2011

Page 41: Hacking Webkit & Its JavaScript Engines

Netflix Video Carousel

Thursday, November 3, 2011

Page 42: Hacking Webkit & Its JavaScript Engines

current pane

current pane

Thursday, November 3, 2011

Page 43: Hacking Webkit & Its JavaScript Engines

current pane

transition pane

transition pane current pane

Thursday, November 3, 2011

Page 44: Hacking Webkit & Its JavaScript Engines

That gives us...Lightweight DOM

Persistent JS References to DOM Elements

Faster / Less-Frequent Mark & Sweep by GC

Fewer Memory Leaks

Thursday, November 3, 2011

Page 45: Hacking Webkit & Its JavaScript Engines

Variable Caching

Thursday, November 3, 2011

Page 46: Hacking Webkit & Its JavaScript Engines

<script>Some = { Deeply: { Nested: { array: [1, 2, 3, 4, 5] } }};</script>

setup

Thursday, November 3, 2011

Page 47: Hacking Webkit & Its JavaScript Engines

for (var i = 0, x; i < Some.Deeply.Nested.array.length; i++) { x = Some.Deeply.Nested.array[i];}

var arr = Some.Deeply.Nested.array, ln = arr.length;for (var i = 0, x; i < ln; i++) { x = arr[i];}

no cache

cached var

Thursday, November 3, 2011

Page 48: Hacking Webkit & Its JavaScript Engines

for (var i = 0, x; i < Some.Deeply.Nested.array.length; i++) { x = Some.Deeply.Nested.array[i];}

var arr = Some.Deeply.Nested.array, ln = arr.length;for (var i = 0, x; i < ln; i++) { x = arr[i];}

no cache

cached var

fast

slow

Thursday, November 3, 2011

Page 49: Hacking Webkit & Its JavaScript Engines

Variable Caching

http://jsperf.com/variable-reference-caching

Thursday, November 3, 2011

Page 50: Hacking Webkit & Its JavaScript Engines

Enumeration

Thursday, November 3, 2011

Page 51: Hacking Webkit & Its JavaScript Engines

var i = 0, ln = myArray.length, x;for (; i < ln; i++) { x = myArray[i];}

for (var x in myArray) {

}

var i = 0, x;for (; x = myArray[i]; i++) {

}

var i = myArray.length, x;while (i--) { x = myArray[i];}

index < length

for in

test value truthiness test index truthiness

Thursday, November 3, 2011

Page 52: Hacking Webkit & Its JavaScript Engines

var i = 0, ln = myArray.length, x;for (; i < ln; i++) { x = myArray[i];}

for (var x in myArray) {

}

var i = 0, x;for (; x = myArray[i]; i++) {

}

var i = myArray.length, x;while (i--) { x = myArray[i];}

slowest

depends...? depends...?

index < length

for in

test value truthiness test index truthiness

fastest

Thursday, November 3, 2011

Page 53: Hacking Webkit & Its JavaScript Engines

Enumeration

http://jsperf.com/optimal-array-enumeration

Thursday, November 3, 2011

Page 54: Hacking Webkit & Its JavaScript Engines

Dirty Math Hack

Thursday, November 3, 2011

Page 55: Hacking Webkit & Its JavaScript Engines

<script>var myArray = [];for (var i = 0; i < 65535; i++) { myArray.push(Math.random() * 10000);}</script>

setup

Thursday, November 3, 2011

Page 56: Hacking Webkit & Its JavaScript Engines

var i = 0, ln = myArray.length;for (var x; i < ln; i++) { x = Math.round(myArray[i]);}

var i = 0, ln = myArray.length;for (var x; i < ln; i++) { x = (0.5 + myArray[i]) << 0;}

Math.round in loop

inline left bit shift

Thursday, November 3, 2011

Page 57: Hacking Webkit & Its JavaScript Engines

var i = 0, ln = myArray.length;for (var x; i < ln; i++) { x = Math.round(myArray[i]);}

var i = 0, ln = myArray.length;for (var x; i < ln; i++) { x = (0.5 + myArray[i]) << 0;}

Math.round in loop

inline left bit shift

fastslow

Thursday, November 3, 2011

Page 58: Hacking Webkit & Its JavaScript Engines

Math

http://jsperf.com/jit-part-2

Thursday, November 3, 2011

Page 59: Hacking Webkit & Its JavaScript Engines

Math - Inline Equivalents

Math.floor(x) === (x << 0)Math.round(x) === (0.5 + x << 0)Math.ceil(x) === (x === x << 0 ? x : x + 1 << 0)...

Thursday, November 3, 2011

Page 60: Hacking Webkit & Its JavaScript Engines

Don’t Trust Intuition!

Thursday, November 3, 2011

Page 61: Hacking Webkit & Its JavaScript Engines

Code Analysis

Thursday, November 3, 2011

Page 62: Hacking Webkit & Its JavaScript Engines

Demo

Thursday, November 3, 2011

Page 63: Hacking Webkit & Its JavaScript Engines

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Thursday, November 3, 2011

Page 64: Hacking Webkit & Its JavaScript Engines

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Thursday, November 3, 2011

Page 65: Hacking Webkit & Its JavaScript Engines

"type": "IfStatement","test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null

if (x == y) foo();

Danger!

Thursday, November 3, 2011

Page 66: Hacking Webkit & Its JavaScript Engines

Wrap Up

Thursday, November 3, 2011

Page 67: Hacking Webkit & Its JavaScript Engines

THANK YOU!

Thursday, November 3, 2011

Page 68: Hacking Webkit & Its JavaScript Engines

QUESTIONS?

ariya @ sencha.com

ariyahidayat

ariya.ofilabs.com

jarred @ sencha.com

jarrednicholls

about.me/jarrednicholls

Thursday, November 3, 2011

Page 69: Hacking Webkit & Its JavaScript Engines

Hardware AccelerationToday 3:00pm

Thursday, November 3, 2011

Page 70: Hacking Webkit & Its JavaScript Engines

Typical Dynamic Lang.

Parser Runtime

Interpreter

Thursday, November 3, 2011

Page 71: Hacking Webkit & Its JavaScript Engines

How does JavaScript talk to the DOM?

Thursday, November 3, 2011

Page 72: Hacking Webkit & Its JavaScript Engines

How does JavaScript talk to the DOM?

BINDINGS!

Thursday, November 3, 2011

Page 73: Hacking Webkit & Its JavaScript Engines

window.location.href

Thursday, November 3, 2011

Page 74: Hacking Webkit & Its JavaScript Engines

window.location.href

Thursday, November 3, 2011