Hacking Webkit & Its JavaScript Engines

Post on 07-Nov-2014

6.710 views 0 download

Tags:

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

Thursday, November 3, 2011

forget to run

the tests

Typical Scenario

This is awesome!

Thursday, November 3, 2011

Ariya Hidayat & Jarred NichollsSencha

Twitter: @ariyahidayat @jarrednicholls

HACKING WEBKIT & ITS JAVASCRIPT ENGINES

Thursday, November 3, 2011

What is WebKit?

Thursday, November 3, 2011

Browser at a High LevelUser Interface

Browser Engine

Graphics Stack

Data P

ersistence

Render Engine

JavaScript Engine

Networking I/O

Thursday, November 3, 2011

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

≠Thursday, November 3, 2011

⊂Thursday, November 3, 2011

WebKit isEVERYWHERE!

Thursday, November 3, 2011

Even in your living room!

Thursday, November 3, 2011

How?

Thursday, November 3, 2011

Client InterfaceThursday, November 3, 2011

WebKit ComponentsRender Engine

WebCore

JavaScript Engine (JSC/V8)Client Interface

HTML

DOMCSS

SVG

Canvas

Thursday, November 3, 2011

Port Abstraction

Client Interface

Networking I/O

GraphicsThemeEventsClipboard

Thread Geolocation Timer

API CallsEvents

Port(Chrome, Safari, etc.)

Thursday, November 3, 2011

<input type=”number” />

WebKit Port

Paint me some spin

buttons, STAT!

I know how to do that!

Thursday, November 3, 2011

<input type=”number” />

WebKit

right there

please, kthx

Thursday, November 3, 2011

<input type=”number” />

Port

Piece of cake!

lookin’ sexy!

Thursday, November 3, 2011

<input type=”number” />

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

Thursday, November 3, 2011

<input type=”number” />

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

Theme Interface

Client Interface

Theme

RenderTheme->paint()

PortpaintInnerSpinButton

Thursday, November 3, 2011

Command LineWebKit

Thursday, November 3, 2011

Demo

Thursday, November 3, 2011

How’d you do that!?

Thursday, November 3, 2011

Headless WebKit

Thursday, November 3, 2011

“Headless”

Thursday, November 3, 2011

Display

Paint

Layout

Normal Browser

Thursday, November 3, 2011

Display

Paint

Layout

Headless

X

Thursday, November 3, 2011

What’s in it for me?

Thursday, November 3, 2011

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

Continuous integration

Pixel-perfect regression tests

Web scraping

...

Thursday, November 3, 2011

Demo

Thursday, November 3, 2011

JavaScript Optimizations & Best

Practices

Thursday, November 3, 2011

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

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

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

Best PracticesBatching DOM Operations

Reuse & Recycle DOM

Cache Variables

Optimal Enumeration

Dirty Math Hack

Thursday, November 3, 2011

Batch DOM Operations

Thursday, November 3, 2011

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

setup

Thursday, November 3, 2011

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

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

Batch DOM Operations

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

Thursday, November 3, 2011

Reuse & Recycle

Thursday, November 3, 2011

Netflix Video Carousel

Thursday, November 3, 2011

current pane

current pane

Thursday, November 3, 2011

current pane

transition pane

transition pane current pane

Thursday, November 3, 2011

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

Variable Caching

Thursday, November 3, 2011

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

setup

Thursday, November 3, 2011

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

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

Variable Caching

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

Thursday, November 3, 2011

Enumeration

Thursday, November 3, 2011

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

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

Enumeration

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

Thursday, November 3, 2011

Dirty Math Hack

Thursday, November 3, 2011

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

setup

Thursday, November 3, 2011

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

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

Math

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

Thursday, November 3, 2011

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

Don’t Trust Intuition!

Thursday, November 3, 2011

Code Analysis

Thursday, November 3, 2011

Demo

Thursday, November 3, 2011

"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

"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

"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

Wrap Up

Thursday, November 3, 2011

THANK YOU!

Thursday, November 3, 2011

QUESTIONS?

ariya @ sencha.com

ariyahidayat

ariya.ofilabs.com

jarred @ sencha.com

jarrednicholls

about.me/jarrednicholls

Thursday, November 3, 2011

Hardware AccelerationToday 3:00pm

Thursday, November 3, 2011

Typical Dynamic Lang.

Parser Runtime

Interpreter

Thursday, November 3, 2011

How does JavaScript talk to the DOM?

Thursday, November 3, 2011

How does JavaScript talk to the DOM?

BINDINGS!

Thursday, November 3, 2011

window.location.href

Thursday, November 3, 2011

window.location.href

Thursday, November 3, 2011