@floatdrop – History – bit.ly/crcfd



@floatdrop – History – bit.ly/crcfd

0 0


nodejs-shri-2013

Presentation on NodeJS

On Github floatdrop / nodejs-shri-2013

@floatdrop

bit.ly/nodejs-shri

Node.JS

History

bit.ly/crcfd

1987

on mouseUp
	get the selection
	if it is empty then as "Dial what number?"
	if it is not empty then
		push this card
		visual effect zoom open
		go to stack "Phone"
		dial it
		pop card
	end if
end mouseUp
						

1987

Расчитан на обработку событий

Был написан за 10 дней

Function as first-class objects

Прототипное наследование из Self

1995

Inheritance modifies the lookup procedure by extending the search to other objects. These objects are located via parent slots, which are a special kind of data slot. Any data slot can be designated a parent, by attaching an asterisk to the slot name.

AJAX

2005

Node.JS

JavaScript on server

2009

The term Ajax was coined on 18 February 2005 by Jesse James Garrett in an article entitled "Ajax: A New Approach to Web Applications", based on techniques used on Google pages.[1] On 5 April 2006, the World Wide Web Consortium (W3C) released the first draft specification for the XMLHttpRequest object in an attempt to create an official web standard.[6]

Apache + PHP = ❤

index.php

$result = mysqli_query( $con,
	"SELECT * FROM Persons");

while($row = mysqli_fetch_array($result)) {
  echo $row['Name']."\n";
}

file_put_contents("access.log", 
	"Request done")

Single-thread server

Pictures from node-explained

Multi-thread server

Ryan Dahl

 

I/O has to be done differently.We are doing it wrong

 

bit.ly/jsconf-node

event-loop сервер

event-loop server

bit.ly/bombanulo

event-loop server

goes wrong

JavaScript is slow

bit.ly/bombanulo-2

"Simple" benchmark

bit.ly/dumb-test

Installing

nodejs.org/download

Running

Running

Running

Running

windows

window

document

document

global

global

global

process

process

Modules

require('antigravity')

module.js

function HelloWorld () {
  console.log('Hello world');
}

console.log('Module loaded');

index.js

require('./module');

index.js

require('./module');

HelloWorld();

module.js

function HelloWorld () {
  console.log('Hello world');
}

console.log('Module loaded');

exports.HelloWorld = HelloWorld;

index.js

var module = require('./module');

module.HelloWorld();

module.js

function HelloWorld () {
  console.log('Hello world');
}

console.log('Module loaded');

global.HelloWorld = HelloWorld;

index.js

require('./module');

HelloWorld();

exports vs module.exports

russian.js

var en_translation = {
  yes: 'Нет',
  no: 'Да' 
};

exports = en_translation;

exports vs module.exports

russian.js

var en_translation = {
  yes: 'Да',
  no: 'Нет' 
};

module.exports = en_translation;

exports vs module.exports

russian.json

{
	"yes": "да",
	"no": "нет"
}

requrie('./directory')

require('./directory/index.json') require('./directory/index.js') require('./directory/' + require('./directory/package.json').main);
require('http')
require('express')
require('./index.js')
require('./config.json')
require('./module') // Directory

Simple web-server

Simple web-server

Simple web-server

Simple web-server

Simple web-server

index.js

var http = require('http');

function helloService(request, response) {
	response.end("Hello, stranger!");
}

var server = http.createServer(helloService);

module.exports = server;

Run, Forest, Run!

Run, Forest, Run!

Run, Forest, Run!

Run, Forest, Run!

Simple web-server

node_modules

Run, Forest, Run!

Run, Forest, Run!

Run, Forest, Run!

Run, Forest, Run!

require("antigravity")

in /home/user/programm/library/index.js

/home/user/programm/library/node_modules/antigravity /home/user/programm/node_modules/antigravity /home/user/node_modules/antigravity /home/node_modules/antigravity /node_modules/antigravity

NODE_PATH

$HOME/.node_modules, $HOME/.node_libraries, $PREFIX/lib/node

node_modules/antigravity.js

module.exports = new Date();

index.js

console.log(require("antigravity"));

node_modules/antigravity.js

console.log(module);

module.exports = new Date();

Circular dependencies

Circular dependencies

a.js

var b = require('./b.js');
console.log("B: ", b);

b.js

var a = require('./a.js');
console.log("A: ", a);

Circular dependencies

a.js

module.exports.hello = "Hello from A";
var b = require('./b.js');
module.exports.helloFromB = b.hello;
console.log("B: ", b);

b.js

module.exports.hello = "Hello from B";
var a = require('./a.js');
module.exports.helloFromA = a.hello;
console.log("A: ", a);
modulecounts.com

Installing module

Installing module

Installing module

Installing module

Installing module

Nested dependencies

pros / cons

+ Version independent

- Wieght more

package.json

{
  "name": "express",
  "version": "3.4.4",
  "dependencies": {
    "connect": "2.11.0", "commander": "1.3.2", "range-parser": "0.0.4", "mkdirp": "0.3.5", "cookie": "0.1.0", "buffer-crc32": "0.2.1", "fresh": "0.2.0", "methods": "0.1.0", "send": "0.1.4", "cookie-signature": "1.0.1", "debug": "*"
  },
  "devDependencies": {
    "ejs": "*", "mocha": "*", "jade": "0.30.0", "hjs": "*", "stylus": "*", "should": "2", "connect-redis": "*", "marked": "*", "supertest": "0.8.1 - 1"
  },
  "main": "index",
  "bin": {
    "express": "./bin/express"
  },
  "scripts": {
    "prepublish": "npm prune",
    "test": "make test"
  },
  "engines": {
    "node": "*"
  }
}
						

Express application

var express = require('express');
var app = express();
app.get('/', function(req, res) { res.end('Hello!'); });
app.listen(3000);

Event loop

bit.ly/kantor-node

joyent/node - node.cc

joyent/node - env-inl.h

joyent/libuv - loop.c

joyent/libuv - loop.c

static int uv__loop_init(uv_loop_t* loop, int default_loop) {
	// ...
	RB_INIT(&loop->timer_handles);
	QUEUE_INIT(&loop->wq);
	QUEUE_INIT(&loop->active_reqs);
	QUEUE_INIT(&loop->idle_handles);
	QUEUE_INIT(&loop->async_handles);
	QUEUE_INIT(&loop->check_handles);
	QUEUE_INIT(&loop->prepare_handles);
	QUEUE_INIT(&loop->handle_queue);
	QUEUE_INIT(&loop->pending_queue);
	QUEUE_INIT(&loop->watcher_queue);

	err = uv__platform_loop_init(loop, default_loop);
	// ...
}

uv__platform_loop_init

  • kqueue
  • epoll

joyent/node - node.cc

joyent/node - core.c : 258

int uv_run(uv_loop_t* loop, uv_run_mode mode) {
	r = uv__loop_alive(loop);
	while (r != 0 && loop->stop_flag == 0) {
		// ...
		uv__update_time(loop);
		uv__run_timers(loop);
		uv__io_poll(loop, timeout);
		// ...
	}
}
static int uv__loop_alive(uv_loop_t* loop) {
  return uv__has_active_handles(loop) ||
         uv__has_active_reqs(loop) ||
         loop->closing_handles != NULL;
}

Fibonacci

function fibonacci(n) {
  if (n < 2)
    return 1;
  else
    return fibonacci(n-2) + fibonacci(n-1);
}

require('http').createServer(function (req, res) {
  res.end("40: " + fibonacci(40));
}).listen(8005);

Fibonacci

Requests per second: 0.61
Time per request: 1634.748 ms (vs 5676 ms)

setTimeout, setImmediate, process.nextTick

process.nextTick* Input / Output setImmediate setTimeout

Fibonacci

function fibonacci(i, n, f1, f2, res) {
  if (i >= n)
    res.end(n + ": " + (f1 + f2));
  else
    setImmediate(function() {
        fibonacci(i + 1, n, f2, f1 + f2, res);
    });
}

require('http').createServer(function (req, res) {
  fibonacci(0, 1473, 1, 1, res);
}).listen(8005);

Fibonacci

Requests per second: 264.55
Time per request: 3.780 ms

Streams

0.10.x

bit.ly/streams-node
$ cut -f 1 | uniq -c | sort -n

Streams in Node.JS

fs - createReadStream, createWriteStream process - stdin, stderr and stdout http - client requests, server response tcp - sockets zlib - createUnzip... crypto - createCipher

Crypto service

var app = require('express')();
app.post('/:algo/:secret', function(req, res) {
	// Some magic should be applied here
	res.end(req.params.algo + " " + req.params.secret);
});
app.listen(31337);

Crypto stdin

var cipher = require('crypto')
    .createCipher('aes192', 'secret');

process.stdin.pipe(cipher).pipe(process.stdout);

Crypto service

var app = require('express')();
app.get('/:algo/:secret', function(req, res) {
    var cipher = require('crypto')
        .createCipher(req.params.algo, req.params.secret);
    req.pipe(cipher).pipe(res);
});
app.listen(31337);

Push vs Pull streams

Pull streams

Push streams

Streams in Node.JS are Push

ReadableStream. Events:

data, end, close, error, readable

ReadableStream

data event

process.stdin.on('data', 
function(chunk) {
    console.log(chunk); 
});

WriteableStream. Events

finish, pipe, unpipe, drain

WriteableStream. Methods

write method

var backpressure = process.stdout.write('data');

Writeable stream

backpressure

var backpressure = process.stdout.write('data');

This return value is strictly advisory. You MAY continue to write, even if it returns false. However, writes will be buffered in memory, so it is best not to do this excessively. Instead, wait for the drain event before writing more data.

Спасибо за внимение

Вопросы?