Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Server side JavaScript: going all the way


Published on

Node has captured the attention of early adopters by clearly differentiating itself as being asynchronous from the ground up while remaining accessible. Now that server side JavaScript is at the cutting edge of the asynchronous, real time web, it is in a much better position to establish itself as the go to language for also making synchronous, CRUD webapps and gain a stronger foothold on the server.

This talk covers the current state of server side JavaScript beyond Node. It introduces Common Node, a synchronous CommonJS compatibility layer using node-fibers which bridges the gap between the different platforms. We look into Common Node's internals, compare its performance to that of other implementations such as RingoJS and go through some ideal use cases.

Published in: Technology, Education
  • Login to see the comments

Server side JavaScript: going all the way

  1. Server side JavaScript: going all the way #rejectjs 29.09.11
  2. /me <ul><li>#startups </li></ul><ul><li>#akshell </li></ul><ul><li>#ringojs </li></ul><ul><li>#moscowjs </li></ul><ul><li>#dailyjs </li></ul>
  4. Node.js <ul><li>Ideal use cases </li></ul><ul><ul><li>Real time apps, infrastructure duct tape </li></ul></ul><ul><li>Badly suited for </li></ul><ul><ul><li>CRUD, command line tools, CPU heavy loads </li></ul></ul><ul><li>Easy to get started with </li></ul><ul><ul><li>Difficult to get into production </li></ul></ul>
  6. Akshell NarwhalJS RingoJS Wakanda GPSEE v8cgi
  7. ServerJS Fragmentation
  8. <ul><li>Sync vs. Async </li></ul>
  10. <ul><li>“ async style is kicking sync style's ass” </li></ul>
  12. <ul><li>sync is “on top of” async – a higher level of abstraction </li></ul>
  13. Sync vs. Async function add(callback) { http.get(url1, function(response1) { var part1 =; http.get(url2, function(response2) { var part2 =; callback(part1 + part2); } } }
  14. Sync vs. Async http.get(url1).data + http.get(url2).data
  15. Interoperability <ul><li>Pure JavaScript modules run anywhere </li></ul><ul><ul><li>Templating, parsing, formatting, encoding </li></ul></ul><ul><li>Anything doing I/O exposes sync or async API </li></ul><ul><ul><li>Defines the interface exposed by higher level packages </li></ul></ul>
  17. CommonJS /1 <ul><li>Assert </li></ul><ul><li>Console </li></ul><ul><li>System/1.0 </li></ul>
  18. CommonJS /2 <ul><li>Binary/B </li></ul><ul><li>IO/A </li></ul><ul><li>Filesystem/A </li></ul><ul><li>JSGI 0.3 </li></ul><ul><li>HTTP Client /A </li></ul><ul><li>Sockets/A </li></ul><ul><li>Subprocess </li></ul>
  19. common-node <ul><li>Implements synchronous CommonJS proposals using node-fibers </li></ul><ul><li>Traceur to support latest language features </li></ul><ul><li>Bridges the gap between platforms, sync and async </li></ul>
  20. <ul><li>What it's good for? </li></ul>
  21. everything!
  22. What's it actually good for? <ul><li>Business logic </li></ul><ul><ul><li>Lots of state, fine grained error handling </li></ul></ul><ul><li>CRUD </li></ul><ul><ul><li>Java, Rails, PHP, Python </li></ul></ul><ul><li>Command line tools </li></ul><ul><li>Cross platform portability </li></ul>
  23. On Threads & Fibers <ul><li>“ Threads suck” </li></ul><ul><ul><li>- Brendan Eich, creator of JavaScript </li></ul></ul><ul><li>“ Fibers introduce interleaving hazards — Any function call can cause a yield and then your closure invariants *may be* broken.” </li></ul><ul><ul><li>- Kris Kowal, creator of CommonJS/Modules </li></ul></ul>
  24. Concurrency in JavaScript <ul><li>“ You shouldn’t think that event-based concurrency eliminates synchronization, or shared memory, or anything other than preemption” - Sam Tobin-Hochstadt, member of the Ecma TC39 committee on JavaScript </li></ul>
  25. fibers /1 <ul><li>Co routine implementation using libcoro </li></ul><ul><li>Co-operative multitasking </li></ul><ul><li>Implicit synchronization </li></ul>
  26. fibers /2 <ul><li>Not a fork or a hack of Node </li></ul><ul><li>No wrapper script required </li></ul><ul><li>V8 Context and 64KB stack per fiber </li></ul><ul><li>Will run on Windows </li></ul>
  27. Node.js process [ closure closure t ->
  28. RingoJS (0.8) process thread stack process thread stack t ->
  29. Common Node (fibers) process fiber stack fiber stack [ t ->
  30. Comparison Node.js Common Node RingoJS Process Count Single Single Multiple State Closure Fiber Stack Thread Stack Multitasking User (co-op) Library (co-op) OS (pre-empt) Memory Usage Low Low High “ Jitter” High High Low
  31. Internals - sleep <ul><li>exports.sleep = function(milliseconds) { </li></ul><ul><li>var fiber = Fiber.current; </li></ul><ul><li>setTimeout(function() { </li></ul><ul><li>; </li></ul><ul><li>}, milliseconds); </li></ul><ul><li>yield(); </li></ul><ul><li>} ; </li></ul>
  32. Internals – HttpClient /1 <ul><li>var req = http.request(options, function(r) { </li></ul><ul><li>; </li></ul><ul><li>}); </li></ul><ul><li>req.on('error', function(error) { </li></ul><ul><li>; </li></ul><ul><li>}); </li></ul><ul><li>this.guts.body.forEach(function(block) { </li></ul><ul><li>req.write(block.buffer || block); </li></ul><ul><li>}); </li></ul><ul><li>req.end(); </li></ul>
  33. Internals – HttpClient /2 <ul><li>var result = yield(); </li></ul><ul><li>if(result instanceof Error) </li></ul><ul><li>throw new Error(result.message); </li></ul><ul><li>return { </li></ul><ul><li>status: result.statusCode, </li></ul><ul><li>headers: result.headers, </li></ul><ul><li>body: new Stream(result) </li></ul><ul><li>}; </li></ul>
  34. Internals - IO <ul><li>// on 'data', 'end', 'error' </li></ul><ul><li>// pause when draining </li></ul><ul><li>var listeners = attach(; </li></ul><ul><li>var data = yield(); </li></ul><ul><li>detach(, listeners); </li></ul>
  35. <ul><li>Examples </li></ul>
  36. JSGI <ul><li> = function(request) { </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li>headers: {}, </li></ul><ul><li>body: ['Hello World!'] </li></ul><ul><li>// openRaw(module.filename) </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  37. Spawn & Sleep <ul><li> = function(request) { </li></ul><ul><li>spawn(function() { </li></ul><ul><li>sleep(10000); </li></ul><ul><li>console.log('Hello Server!'); </li></ul><ul><li>}); </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li>headers: {}, </li></ul><ul><li>body: ['Hello Client!'] </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  38. HTTP Proxy <ul><li>var HttpClient = require('httpclient').HttpClient; </li></ul><ul><li> = function(req) { </li></ul><ul><li>req.url = ''; </li></ul><ul><li>return new HttpClient(req).finish(); </li></ul><ul><li>}; </li></ul>
  39. Twitter Streaming /1 <ul><li>var stream = new TextStream( new HttpClient({ </li></ul><ul><li>method: 'POST', </li></ul><ul><li>url: '...', </li></ul><ul><li>headers: {} </li></ul><ul><li>body: ['track='+system.args[4]], </li></ul><ul><li>timeout: 10000 </li></ul><ul><li>}).finish().body); </li></ul>
  40. Twitter Streaming /2 <ul><li>var line; </li></ul><ul><li>while(true) { </li></ul><ul><li>line = stream.readLine(); </li></ul><ul><li>if(!line.length) break; </li></ul><ul><li>if(line.length > 1) { </li></ul><ul><li>var message = JSON.parse(line); </li></ul><ul><li>console.log(message.text); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  41. Telnet Chat /1 <ul><li>var socket = require('socket'); </li></ul><ul><li>var server = new socket.Socket(); </li></ul><ul><li>var clients = [], client; </li></ul><ul><li>server.bind('localhost', 23); </li></ul>
  42. Telnet Chat /2 <ul><li>while(true) { </li></ul><ul><li>clients.push(client = server.accept().getStream()); </li></ul><ul><li>spawn(function() { var stream = client, line; </li></ul><ul><li>while((line = { </li></ul><ul><li>clients.forEach(function(c) { </li></ul><ul><li>if(stream != c) </li></ul><ul><li>c.write(line); </li></ul><ul><li>}); </li></ul><ul><li>} </li></ul><ul><li>clients.splice(clients.indexOf(stream), 1); </li></ul><ul><li>}); </li></ul><ul><li>} </li></ul>
  43. Demo <ul><li>telnet </li></ul>
  44. Benchmarks ab -n 50000 -c 50
  45. hello-world <ul><li> = function() { </li></ul><ul><ul><li>return { </li></ul></ul><ul><ul><ul><li>status: 200, </li></ul></ul></ul><ul><ul><ul><li>headers: { </li></ul></ul></ul><ul><ul><ul><ul><li>'Content-Type': 'text/plain' </li></ul></ul></ul></ul><ul><ul><ul><li>}, </li></ul></ul></ul><ul><ul><ul><li>body: ['Hello World!n'] </li></ul></ul></ul><ul><ul><li>}; </li></ul></ul><ul><li>}; </li></ul>
  47. string-alloc <ul><li> = function(request) { </li></ul><ul><ul><li>for( var i = 1; i <= 50; i++) </li></ul></ul><ul><ul><ul><li>b.decodeToString(&quot;ascii&quot;); </li></ul></ul></ul><ul><ul><li>return { </li></ul></ul><ul><ul><ul><li>status: 200, </li></ul></ul></ul><ul><ul><ul><li>headers: {}, </li></ul></ul></ul><ul><ul><ul><li>body: [b] </li></ul></ul></ul><ul><ul><li>}; </li></ul></ul><ul><li>}; </li></ul>
  49. parse-json <ul><li> = function(request) { </li></ul><ul><ul><li>JSON.parse(json); </li></ul></ul><ul><ul><li>return { </li></ul></ul><ul><ul><ul><li>status: 200, </li></ul></ul></ul><ul><ul><ul><li>headers: {}, </li></ul></ul></ul><ul><ul><ul><li>body: [json] </li></ul></ul></ul><ul><ul><li>}; </li></ul></ul><ul><li>}; </li></ul>
  51. static-file <ul><li> = function() { </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li>headers: {}, </li></ul><ul><li>body: openRaw('../') </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  53. set-timeout <ul><li> = function() { </li></ul><ul><li>sleep(100); </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li>headers: {}, </li></ul><ul><li>body: [] </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  55. Throughput
  56. SyncJS Fragmentation
  57. Road map <ul><li>common-utils </li></ul><ul><li>tests in separate project </li></ul><ul><li>narhwal-mongodb fork </li></ul><ul><li>hns/stick fork </li></ul><ul><li>higher level packages (see project wiki) </li></ul>
  58. Contributing <ul><li>Google “ common node ” </li></ul><ul><li> </li></ul><ul><li>npm -g install common-node </li></ul>
  59. <ul><li>Thank you! </li></ul><ul><li>@olegpodsechin </li></ul>