Server side JavaScript: going all the way #rejectjs 29.09.11
/me <ul><li>#startups </li></ul><ul><li>#akshell </li></ul><ul><li>#ringojs </li></ul><ul><li>#moscowjs </li></ul><ul><li>...
 
Node.js <ul><li>Ideal use cases </li></ul><ul><ul><li>Real time apps, infrastructure duct tape </li></ul></ul><ul><li>Badl...
 
Akshell NarwhalJS RingoJS Wakanda GPSEE v8cgi
ServerJS Fragmentation
<ul><li>Sync vs. Async </li></ul>
 
<ul><li>“ async style is kicking sync style's ass” </li></ul>
 
<ul><li>sync is “on top of” async –  a higher level of abstraction  </li></ul>
Sync   vs.  Async   function add(callback) { http.get(url1, function(response1) { var part1 = response1.data; http.get(url...
Sync  vs.   Async http.get(url1).data + http.get(url2).data
Interoperability <ul><li>Pure JavaScript modules run anywhere </li></ul><ul><ul><li>Templating, parsing, formatting, encod...
 
CommonJS /1 <ul><li>Assert </li></ul><ul><li>Console </li></ul><ul><li>System/1.0 </li></ul>
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><u...
common-node <ul><li>Implements  synchronous  CommonJS proposals using node-fibers  </li></ul><ul><li>Traceur to support la...
<ul><li>What it's good for? </li></ul>
everything!
What's it  actually  good for? <ul><li>Business logic </li></ul><ul><ul><li>Lots of state, fine grained error handling </l...
On Threads & Fibers <ul><li>“ Threads suck”  </li></ul><ul><ul><li>- Brendan Eich, creator of JavaScript </li></ul></ul><u...
Concurrency in JavaScript <ul><li>“ You shouldn’t think that event-based concurrency eliminates synchronization, or shared...
fibers /1 <ul><li>Co routine implementation using libcoro  </li></ul><ul><li>Co-operative multitasking </li></ul><ul><li>I...
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 a...
Node.js process [ closure closure t  ->
RingoJS (0.8) process thread  stack process thread  stack t  ->
Common Node (fibers) process fiber stack fiber stack [ t  ->
Comparison Node.js Common Node RingoJS Process Count Single Single Multiple State Closure Fiber Stack Thread Stack Multita...
Internals - sleep <ul><li>exports.sleep = function(milliseconds) { </li></ul><ul><li>var fiber = Fiber.current; </li></ul>...
Internals – HttpClient /1 <ul><li>var req = http.request(options, function(r) { </li></ul><ul><li>fiber.run(r); </li></ul>...
Internals – HttpClient /2 <ul><li>var result = yield(); </li></ul><ul><li>if(result instanceof Error) </li></ul><ul><li>th...
Internals - IO <ul><li>// on 'data', 'end', 'error' </li></ul><ul><li>// pause when draining </li></ul><ul><li>var listene...
<ul><li>Examples </li></ul>
JSGI <ul><li>exports.app = function(request) { </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li...
Spawn & Sleep <ul><li>exports.app = function(request) { </li></ul><ul><li>spawn(function() { </li></ul><ul><li>sleep(10000...
HTTP Proxy <ul><li>var HttpClient = require('httpclient').HttpClient; </li></ul><ul><li>exports.app = function(req) { </li...
Twitter Streaming /1 <ul><li>var stream = new TextStream(   new HttpClient({ </li></ul><ul><li>method:  'POST', </li></ul>...
Twitter Streaming /2 <ul><li>var line; </li></ul><ul><li>while(true) { </li></ul><ul><li>line = stream.readLine(); </li></...
Telnet Chat /1 <ul><li>var socket = require('socket'); </li></ul><ul><li>var server = new socket.Socket();  </li></ul><ul>...
Telnet Chat /2 <ul><li>while(true) { </li></ul><ul><li>clients.push(client = server.accept().getStream()); </li></ul><ul><...
Demo <ul><li>telnet 10.0.0.97 </li></ul>
Benchmarks ab -n 50000 -c 50
hello-world <ul><li>exports.app = function() { </li></ul><ul><ul><li>return { </li></ul></ul><ul><ul><ul><li>status: 200, ...
 
string-alloc <ul><li>exports.app = function(request) { </li></ul><ul><ul><li>for( var i = 1; i <= 50; i++) </li></ul></ul>...
 
parse-json <ul><li>exports.app = function(request) { </li></ul><ul><ul><li>JSON.parse(json); </li></ul></ul><ul><ul><li>re...
 
static-file <ul><li>exports.app = function() { </li></ul><ul><li>return {  </li></ul><ul><li>status: 200,  </li></ul><ul><...
 
set-timeout <ul><li>exports.app = function() { </li></ul><ul><li>sleep(100); </li></ul><ul><li>return { </li></ul><ul><li>...
 
Throughput
SyncJS Fragmentation
Road map <ul><li>common-utils </li></ul><ul><li>tests in separate project </li></ul><ul><li>narhwal-mongodb fork </li></ul...
Contributing <ul><li>Google  “ common node ” </li></ul><ul><li>github.com/olegp/common-node/ </li></ul><ul><li>npm -g inst...
<ul><li>Thank you! </li></ul><ul><li>@olegpodsechin </li></ul>
Upcoming SlideShare
Loading in...5
×

Server side JavaScript: going all the way

7,892

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
2 Comments
3 Likes
Statistics
Notes
  • Interesting and very informative. thanks for the presentation.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Direct link to the Common Node project: http://olegp.github.com/common-node/
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
7,892
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
32
Comments
2
Likes
3
Embeds 0
No embeds

No notes for slide

Server side JavaScript: going all the way

  1. 1. Server side JavaScript: going all the way #rejectjs 29.09.11
  2. 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>
  3. 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>
  4. 6. Akshell NarwhalJS RingoJS Wakanda GPSEE v8cgi
  5. 7. ServerJS Fragmentation
  6. 8. <ul><li>Sync vs. Async </li></ul>
  7. 10. <ul><li>“ async style is kicking sync style's ass” </li></ul>
  8. 12. <ul><li>sync is “on top of” async – a higher level of abstraction </li></ul>
  9. 13. Sync vs. Async function add(callback) { http.get(url1, function(response1) { var part1 = response1.data; http.get(url2, function(response2) { var part2 = response2.data; callback(part1 + part2); } } }
  10. 14. Sync vs. Async http.get(url1).data + http.get(url2).data
  11. 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>
  12. 17. CommonJS /1 <ul><li>Assert </li></ul><ul><li>Console </li></ul><ul><li>System/1.0 </li></ul>
  13. 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>
  14. 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>
  15. 20. <ul><li>What it's good for? </li></ul>
  16. 21. everything!
  17. 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>
  18. 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>
  19. 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>
  20. 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>
  21. 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>
  22. 27. Node.js process [ closure closure t ->
  23. 28. RingoJS (0.8) process thread stack process thread stack t ->
  24. 29. Common Node (fibers) process fiber stack fiber stack [ t ->
  25. 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
  26. 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>fiber.run(); </li></ul><ul><li>}, milliseconds); </li></ul><ul><li>yield(); </li></ul><ul><li>} ; </li></ul>
  27. 32. Internals – HttpClient /1 <ul><li>var req = http.request(options, function(r) { </li></ul><ul><li>fiber.run(r); </li></ul><ul><li>}); </li></ul><ul><li>req.on('error', function(error) { </li></ul><ul><li>fiber.run(error); </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>
  28. 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>
  29. 34. Internals - IO <ul><li>// on 'data', 'end', 'error' </li></ul><ul><li>// pause when draining </li></ul><ul><li>var listeners = attach(this.stream); </li></ul><ul><li>var data = yield(); </li></ul><ul><li>detach(this.stream, listeners); </li></ul>
  30. 35. <ul><li>Examples </li></ul>
  31. 36. JSGI <ul><li>exports.app = 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>
  32. 37. Spawn & Sleep <ul><li>exports.app = 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>
  33. 38. HTTP Proxy <ul><li>var HttpClient = require('httpclient').HttpClient; </li></ul><ul><li>exports.app = function(req) { </li></ul><ul><li>req.url = 'http://nodejs.org'; </li></ul><ul><li>return new HttpClient(req).finish(); </li></ul><ul><li>}; </li></ul>
  34. 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>
  35. 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>
  36. 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>
  37. 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 = stream.read(null)).length) { </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>
  38. 43. Demo <ul><li>telnet 10.0.0.97 </li></ul>
  39. 44. Benchmarks ab -n 50000 -c 50
  40. 45. hello-world <ul><li>exports.app = 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>
  41. 47. string-alloc <ul><li>exports.app = 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>
  42. 49. parse-json <ul><li>exports.app = 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>
  43. 51. static-file <ul><li>exports.app = function() { </li></ul><ul><li>return { </li></ul><ul><li>status: 200, </li></ul><ul><li>headers: {}, </li></ul><ul><li>body: openRaw('../README.md') </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  44. 53. set-timeout <ul><li>exports.app = 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>
  45. 55. Throughput
  46. 56. SyncJS Fragmentation
  47. 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>
  48. 58. Contributing <ul><li>Google “ common node ” </li></ul><ul><li>github.com/olegp/common-node/ </li></ul><ul><li>npm -g install common-node </li></ul>
  49. 59. <ul><li>Thank you! </li></ul><ul><li>@olegpodsechin </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×