run node run
DESCRIPTION
A brief overview of profiling Node.js and writing code for the V8 runtime.TRANSCRIPT
Agenda
• Benchmarking • V8 JavaScript Tips and Tricks• Inside Crankshaft• Profiling Node
From 365 to 5,000 requests per second.
This shit works. Swears it.
Note: This is complex, but you’ll sleep better at night.
If you can sleep at all.
This is about speed.
Speed is addictive.
Benchmarking
HTTP
$ ab -n1000 –c100 –k http://127.0.0.1/
$ siege –r100 –c100 -b http://127.0.0.1/
JMeter
ab output
Concurrency Level: 100Time taken for tests: 8.680 secondsRequests per second: 11521.27 [#/sec] (mean)Time per request: 8.680 [ms] (mean)Time per request: 0.087 [ms] (mean, across all concurrent requests)
Non-HTTP
var maxRuns = 1000;var start = Date.now();for (var i = 0; i < maxRuns; i++) { // do stuff...}var end = Date.now();
var elapsed = end – start;var timePerRun = elapsed / maxRuns;
console.log(elapsed + ‘ ms’);console.log(timePerRun + ‘ ms/run’
Faster!
Hidden Classes
function Point(x, y) { this.x = x; this.y = y;}
var p1 = new Point(1, 2);var p2 = new Point(3, 4);
Hidden Classes
function Point(x, y) { this.x = x; this.y = y;}
var p1 = new Point(1, 2);var p2 = new Point(3, 4);p2.z = 9; // ohnoes!!
Dictionary Mode
function takeOrder(row) { var order = { food: row.get(‘food’), quantity: row.get(‘qty’); }; process(order);}
Dictionary Mode
function takeOrder(row) { var order = { food: row.get(‘food’), quantity: row.get(‘qty’); }; process(order);}// ohnoes!!!for(var i = 0; i < db.length; i++) { takeOrder(db[i]);}
Try-Catch
try { // hot code} catch(e) { console.log(e);}
Try-Catch
try { process();} catch(e) { console.log(e);}
function process() { // hot code}
Hot Code
• Don’t monkey-patch.• Don’t mix types for the same property.• Avoid dictionary mode.• Set all properties in the constructor.• Move high-performance code out of try-catch.• If array.length < 65000, specify the size.
V8’s Crankshaft is Awesome
Base Compiler
Runtime Profiler
Optimizing Compiler
Deoptimization Support
JavaScript ->Hydrogen ->Lithium ->(Native)
Profiling Node
$ node --prof server.js
Note: Your benchmark will be slower.
$ lsserver.js v8.log
$ export D8_PATH=~/node/src/deps/v8$ ~/nvm/src/node-v0.8.18/deps/v8/tools/mac-tick-processor > profile.log
[JavaScript]: ticks total nonlib name 251 0.5% 0.5% LazyCompile: *Socket.write net.js:465
[C++]: ticks total nonlib name 48625 94.4% 94.4% ___psynch_rw_unlock
[GC]: ticks total nonlib name 263 0.5%
c4milo/node-webkit-agent
$ cat server.jsvar agent = require('webkit-devtools-agent');// create serverconsole.log(process.pid)
$ node server.js22341
$ kill –SIGUSR2 22341$ open http://c4milo.github.com/node-webkit-agent/21.0.1180.57/inspector.html?host=localhost:1337&page=0
More Profiling Options
--trace_opt
• Shows code optimizations.• Good for spotting hot code.
--trace_deopt
• Shows code de-optimizations.• Good for spotting type information changes in
hot code.
“If you ain’t first, you’re last!”
The plumbing should work like greased lightning.
You can’t control everything.
Fail with grace.
Benchmark regularly.
Additional Resources
• Understanding V8• Breaking the JavaScript Speed Limit• V8 Internals• Profiling Node Programs on Mac OS X• Node Webkit Agent
Adios!
@kevinswiber [email protected]