server side javascript: going all the way

59
Server side JavaScript: going all the way #rejectjs 29.09.11

Upload: oleg-podsechin

Post on 12-May-2015

7.727 views

Category:

Technology


0 download

DESCRIPTION

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.

TRANSCRIPT

Page 1: Server side JavaScript: going all the way

Server side JavaScript:going all the way

#rejectjs 29.09.11

Page 2: Server side JavaScript: going all the way

/me

#startups#akshell#ringojs

#moscowjs#dailyjs

Page 3: Server side JavaScript: going all the way
Page 4: Server side JavaScript: going all the way

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

Page 5: Server side JavaScript: going all the way
Page 6: Server side JavaScript: going all the way

Akshell NarwhalJS

RingoJS Wakanda

GPSEE

v8cgi

Page 7: Server side JavaScript: going all the way

ServerJS Fragmentation

Node.js CommonJS Wakanda RingoJS v8cgi Narwhal Common Node Flussperfd Akshell GPSEE0

2000

4000

6000

8000

10000

12000

Project Followers

Group Members

Fo

llow

ers

Page 8: Server side JavaScript: going all the way

Sync vs. Async

Page 9: Server side JavaScript: going all the way
Page 10: Server side JavaScript: going all the way

“async style is kicking sync style's ass”

Page 11: Server side JavaScript: going all the way
Page 12: Server side JavaScript: going all the way

sync is “on top of” async – a higher level of abstraction

Page 13: Server side JavaScript: going all the way

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); } }}

Page 14: Server side JavaScript: going all the way

Sync vs. Async

http.get(url1).data + http.get(url2).data

Page 15: Server side JavaScript: going all the way

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

Page 16: Server side JavaScript: going all the way
Page 17: Server side JavaScript: going all the way

CommonJS /1

Assert Console System/1.0

Page 18: Server side JavaScript: going all the way

CommonJS /2

Binary/B

IO/A Filesystem/A JSGI 0.3 HTTP Client /A Sockets/A Subprocess

Page 19: Server side JavaScript: going all the way

common-node

Implements synchronous CommonJS proposals using node-fibers

Traceur to support latest language features Bridges the gap between platforms, sync and

async

Page 20: Server side JavaScript: going all the way

What it's good for?

Page 21: Server side JavaScript: going all the way

everything!

Page 22: Server side JavaScript: going all the way

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

Page 23: Server side JavaScript: going all the way

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

Page 24: Server side JavaScript: going all the way

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

Page 25: Server side JavaScript: going all the way

fibers /1

Co routine implementation using libcoro

Co-operative multitasking

Implicit synchronization

Page 26: Server side JavaScript: going all the way

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

Page 27: Server side JavaScript: going all the way

Node.js

process[ closure

closure

t →

Page 28: Server side JavaScript: going all the way

RingoJS (0.8)

process thread stack

processthread stack

t →

Page 29: Server side JavaScript: going all the way

Common Node (fibers)

processfiber stack

fiber stack[

t →

Page 30: Server side JavaScript: going all the way

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

Page 31: Server side JavaScript: going all the way

Internals - sleep

exports.sleep = function(milliseconds) {

var fiber = Fiber.current;

setTimeout(function() {

fiber.run();

}, milliseconds);

yield();

};

Page 32: Server side JavaScript: going all the way

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();

Page 33: Server side JavaScript: going all the way

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)

};

Page 34: Server side JavaScript: going all the way

Internals - IO

// on 'data', 'end', 'error'

// pause when draining

var listeners = attach(this.stream);

var data = yield();

detach(this.stream, listeners);

Page 35: Server side JavaScript: going all the way

Examples

Page 36: Server side JavaScript: going all the way

JSGI

exports.app = function(request) {

return {

status: 200,

headers: {},

body: ['Hello World!']

// openRaw(module.filename)

};

};

Page 37: Server side JavaScript: going all the way

Spawn & Sleep

exports.app = function(request) {

spawn(function() {

sleep(10000);

console.log('Hello Server!');

});

return {

status: 200,

headers: {},

body: ['Hello Client!']

};

};

Page 38: Server side JavaScript: going all the way

HTTP Proxy

var HttpClient = require('httpclient').HttpClient;

exports.app = function(req) {

req.url = 'http://nodejs.org';

return new HttpClient(req).finish();

};

Page 39: Server side JavaScript: going all the way

Twitter Streaming /1

var stream = new TextStream( new HttpClient({

method: 'POST',

url: '...',

headers: {}

body: ['track='+system.args[4]],

timeout: 10000

}).finish().body);

Page 40: Server side JavaScript: going all the way

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);

}

}

Page 41: Server side JavaScript: going all the way

Telnet Chat /1

var socket = require('socket');

var server = new socket.Socket();

var clients = [], client;

server.bind('localhost', 23);

Page 42: Server side JavaScript: going all the way

Telnet Chat /2

while(true) {

clients.push(client = server.accept().getStream());

spawn(function() { var stream = client, line;

while((line = stream.read(null)).length) {

clients.forEach(function(c) {

if(stream != c)

c.write(line);

});

}

clients.splice(clients.indexOf(stream), 1);

});

}

Page 43: Server side JavaScript: going all the way

Demo

telnet 10.0.0.97

Page 44: Server side JavaScript: going all the way

Benchmarksab -n 50000 -c 50

Page 45: Server side JavaScript: going all the way

hello-world

exports.app = function() {

return {

status: 200,headers: {

'Content-Type': 'text/plain'},body: ['Hello World!\n']

};

};

Page 46: Server side JavaScript: going all the way
Page 47: Server side JavaScript: going all the way

string-alloc

exports.app = function(request) {

for( var i = 1; i <= 50; i++)

b.decodeToString("ascii");return {

status: 200,headers: {},body: [b]

};

};

Page 48: Server side JavaScript: going all the way
Page 49: Server side JavaScript: going all the way

parse-json

exports.app = function(request) {

JSON.parse(json);

return {

status: 200,headers: {},body: [json]

};

};

Page 50: Server side JavaScript: going all the way
Page 51: Server side JavaScript: going all the way

static-file

exports.app = function() {

return {

status: 200,

headers: {},

body: openRaw('../README.md')

};

};

Page 52: Server side JavaScript: going all the way
Page 53: Server side JavaScript: going all the way

set-timeout

exports.app = function() {

sleep(100);

return {

status: 200,

headers: {},

body: []

};

};

Page 54: Server side JavaScript: going all the way
Page 55: Server side JavaScript: going all the way

Throughput

hello-world string-alloc parse-json static-file set-timeout0

1000

2000

3000

4000

5000

6000

Node.js

Common Node

RingoJS

Page 56: Server side JavaScript: going all the way

SyncJS Fragmentation

Wakanda RingoJS v8cgi Narwhal Common Node Flussperfd Akshell GPSEE0

50

100

150

200

250

300

350

400

Project Followers

Group Members

Fo

llow

ers

Page 57: Server side JavaScript: going all the way

Road map

common-utils tests in separate project narhwal-mongodb fork hns/stick fork higher level packages (see project wiki)

Page 58: Server side JavaScript: going all the way

Contributing

Google “common node”

github.com/olegp/common-node/

npm -g install common-node

Page 59: Server side JavaScript: going all the way

Thank you!

@olegpodsechin