The Future of Server Side JavaScript
/me #startups #akshell #ringojs #moscowjs #dailyjs
 
Node.js Ideal use cases Real time apps, infrastructure duct tape Badly suited for CRUD, command line tools, CPU heavy loads Easy to get started with Difficult to get into production
 
 
Akshell NarwhalJS RingoJS Wakanda GPSEE v8cgi
ServerJS Fragmentation
Sync vs. Async
 
“ async style is kicking sync style's back end”
 
sync is “on top of” async –  a higher level of abstraction
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); } } }
Sync  vs.   Async http.get(url1).data + http.get(url2).data
Interoperability Pure JavaScript modules run anywhere Templating, parsing, formatting, encoding Anything doing I/O exposes sync or async API Defines the interface exposed by higher level packages
 
 
CommonJS /1 Modules/1.1 Packages/1.0 Assert Console System/1.0
CommonJS /2 Binary/B IO/A JSGI 0.3 Filesystem/A
CommonJS /3 HTTP Client /A Sockets/A Subprocess
common-node Implements  synchronous  CommonJS proposals using  node-fibers   Traceur  to support latest language features Bridges the gap between platforms, sync and async
What it's good for?
everything!
What's it  actually  good for? Business logic Lots of state, fine grained error handling CRUD Java, Rails, PHP, Python Command line tools Cross platform portability
On Threads & Fibers “ Threads suck”  - Brendan Eich, creator of JavaScript “ Fibers introduce interleaving hazards — Any function call can cause a yield and then your closure invariants *may be* broken.” - Kris Kowal, creator of CommonJS/Modules
Concurrency in JavaScript “ 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
fibers /1 Co routine implementation using libcoro  Co-operative multitasking Implicit synchronization
fibers /2 Not a fork or a hack of Node No wrapper script required V8 Context and 64KB stack per fiber Will run on Windows
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  ->
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
Internals - sleep exports.sleep = function(milliseconds) { var fiber = Fiber.current; setTimeout(function() { fiber.run(); }, milliseconds); yield(); } ;
Internals – HttpClient /1 var req = http.request(options, function(r) { fiber.run(r); }); req.on('error', function(error) { fiber.run(error); }); this.guts.body.forEach(function(block) { req.write(block.buffer || block); }); req.end();
Internals – HttpClient /2 var result = yield(); if(result instanceof Error) throw new Error(result.message); return { status: result.statusCode, headers: result.headers, body: new Stream(result) };
Internals - IO // on 'data', 'end', 'error' // pause when draining var listeners = attach(this.stream); var data = yield(); detach(this.stream, listeners);
Examples
JSGI exports.app = function(request) { return { status: 200, headers: {}, body: ['Hello World!']  // openRaw(module.filename) }; };
Spawn & Sleep exports.app = function(request) { spawn(function() { sleep(10000); console.log('Hello Server!'); }); return { status: 200, headers: {}, body: ['Hello Client!'] }; };
HTTP Proxy var HttpClient = require('httpclient').HttpClient; exports.app = function(req) { req.url = 'http://nodejs.org'; return new HttpClient(req).finish(); };
Twitter Streaming /1 var stream = new TextStream(   new HttpClient({ method:  'POST', url:  '...', headers: {} body: ['track='+system.args[4]], timeout: 10000 }).finish().body);
Twitter Streaming /2 var line; while(true) { line = stream.readLine(); if(!line.length) break; if(line.length > 1) { var message = JSON.parse(line); console.log(message.text); } }
Benchmarks ab -n 50000 -c 50
hello-world exports.app = function() { return { status: 200, headers: { 'Content-Type': 'text/plain' }, body: ['Hello World!\n'] }; };
 
string-alloc exports.app = function(request) { for( var i = 1; i <= 50; i++) b.decodeToString(&quot;ascii&quot;); return { status: 200, headers: {}, body: [b] }; };
 
parse-json exports.app = function(request) { JSON.parse(json); return { status: 200, headers: {}, body: [json] }; };
 
static-file exports.app = function() { return {  status: 200,  headers: {},  body:  openRaw('../README.md') }; };
 
set-timeout exports.app = function() { sleep(100); return { status: 200, headers: {}, body: [] }; };
 
Throughput
Contributing Google  “ common node ” github.com/olegp/common-node/ npm -g install common-node
SyncJS Fragmentation
Toolkits vs. Frameworks
 
 
 
 
 
Next Steps Stick backport Database access selectjs.com Higher level packages (wiki)
common-utils base64: encode, decode hash: sha1 etc. url: parse, format, resolve string: format, trim etc. date: format, add, before, after etc. array: contains etc. object: clone, merge etc.
One more thing ... Third party services & APIs olegp/rest-wrapper thelockerproject.org Browser based IDEs (Cloud9, Akshell) Social hosting PINF, automatic redeployment, continuous integration etc.
Summary sync and async will co-exist toolkits instead of frameworks implementation driven de-facto standards we are just getting started!
Thank you! @olegpodsechin

JS everywhere 2011

  • 1.
    The Future ofServer Side JavaScript
  • 2.
    /me #startups #akshell#ringojs #moscowjs #dailyjs
  • 3.
  • 4.
    Node.js Ideal usecases Real time apps, infrastructure duct tape Badly suited for CRUD, command line tools, CPU heavy loads Easy to get started with Difficult to get into production
  • 5.
  • 6.
  • 7.
    Akshell NarwhalJS RingoJSWakanda GPSEE v8cgi
  • 8.
  • 9.
  • 10.
  • 11.
    “ async styleis kicking sync style's back end”
  • 12.
  • 13.
    sync is “ontop of” async – a higher level of abstraction
  • 14.
    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); } } }
  • 15.
    Sync vs. Async http.get(url1).data + http.get(url2).data
  • 16.
    Interoperability Pure JavaScriptmodules run anywhere Templating, parsing, formatting, encoding Anything doing I/O exposes sync or async API Defines the interface exposed by higher level packages
  • 17.
  • 18.
  • 19.
    CommonJS /1 Modules/1.1Packages/1.0 Assert Console System/1.0
  • 20.
    CommonJS /2 Binary/BIO/A JSGI 0.3 Filesystem/A
  • 21.
    CommonJS /3 HTTPClient /A Sockets/A Subprocess
  • 22.
    common-node Implements synchronous CommonJS proposals using node-fibers Traceur to support latest language features Bridges the gap between platforms, sync and async
  • 23.
  • 24.
  • 25.
    What's it actually good for? Business logic Lots of state, fine grained error handling CRUD Java, Rails, PHP, Python Command line tools Cross platform portability
  • 26.
    On Threads &Fibers “ Threads suck” - Brendan Eich, creator of JavaScript “ Fibers introduce interleaving hazards — Any function call can cause a yield and then your closure invariants *may be* broken.” - Kris Kowal, creator of CommonJS/Modules
  • 27.
    Concurrency in JavaScript“ 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
  • 28.
    fibers /1 Coroutine implementation using libcoro Co-operative multitasking Implicit synchronization
  • 29.
    fibers /2 Nota fork or a hack of Node No wrapper script required V8 Context and 64KB stack per fiber Will run on Windows
  • 30.
    Node.js process [closure closure t ->
  • 31.
    RingoJS (0.8) processthread stack process thread stack t ->
  • 32.
    Common Node (fibers)process fiber stack fiber stack [ t ->
  • 33.
    Node.js Common NodeRingoJS 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
  • 34.
    Internals - sleepexports.sleep = function(milliseconds) { var fiber = Fiber.current; setTimeout(function() { fiber.run(); }, milliseconds); yield(); } ;
  • 35.
    Internals – HttpClient/1 var req = http.request(options, function(r) { fiber.run(r); }); req.on('error', function(error) { fiber.run(error); }); this.guts.body.forEach(function(block) { req.write(block.buffer || block); }); req.end();
  • 36.
    Internals – HttpClient/2 var result = yield(); if(result instanceof Error) throw new Error(result.message); return { status: result.statusCode, headers: result.headers, body: new Stream(result) };
  • 37.
    Internals - IO// on 'data', 'end', 'error' // pause when draining var listeners = attach(this.stream); var data = yield(); detach(this.stream, listeners);
  • 38.
  • 39.
    JSGI exports.app =function(request) { return { status: 200, headers: {}, body: ['Hello World!'] // openRaw(module.filename) }; };
  • 40.
    Spawn & Sleepexports.app = function(request) { spawn(function() { sleep(10000); console.log('Hello Server!'); }); return { status: 200, headers: {}, body: ['Hello Client!'] }; };
  • 41.
    HTTP Proxy varHttpClient = require('httpclient').HttpClient; exports.app = function(req) { req.url = 'http://nodejs.org'; return new HttpClient(req).finish(); };
  • 42.
    Twitter Streaming /1var stream = new TextStream( new HttpClient({ method: 'POST', url: '...', headers: {} body: ['track='+system.args[4]], timeout: 10000 }).finish().body);
  • 43.
    Twitter Streaming /2var line; while(true) { line = stream.readLine(); if(!line.length) break; if(line.length > 1) { var message = JSON.parse(line); console.log(message.text); } }
  • 44.
    Benchmarks ab -n50000 -c 50
  • 45.
    hello-world exports.app =function() { return { status: 200, headers: { 'Content-Type': 'text/plain' }, body: ['Hello World!\n'] }; };
  • 46.
  • 47.
    string-alloc exports.app =function(request) { for( var i = 1; i <= 50; i++) b.decodeToString(&quot;ascii&quot;); return { status: 200, headers: {}, body: [b] }; };
  • 48.
  • 49.
    parse-json exports.app =function(request) { JSON.parse(json); return { status: 200, headers: {}, body: [json] }; };
  • 50.
  • 51.
    static-file exports.app =function() { return { status: 200, headers: {}, body: openRaw('../README.md') }; };
  • 52.
  • 53.
    set-timeout exports.app =function() { sleep(100); return { status: 200, headers: {}, body: [] }; };
  • 54.
  • 55.
  • 56.
    Contributing Google “ common node ” github.com/olegp/common-node/ npm -g install common-node
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
    Next Steps Stickbackport Database access selectjs.com Higher level packages (wiki)
  • 65.
    common-utils base64: encode,decode hash: sha1 etc. url: parse, format, resolve string: format, trim etc. date: format, add, before, after etc. array: contains etc. object: clone, merge etc.
  • 66.
    One more thing... Third party services & APIs olegp/rest-wrapper thelockerproject.org Browser based IDEs (Cloud9, Akshell) Social hosting PINF, automatic redeployment, continuous integration etc.
  • 67.
    Summary sync andasync will co-exist toolkits instead of frameworks implementation driven de-facto standards we are just getting started!
  • 68.