node.js
                            A quick tour




                                           by Felix Geisendörfer
Donnerstag, 4. März 2010                                           1
Who is talking?

                    • node.js hacker

                    • Cofounder of Debuggable

                    • CakePHP core alumnus

Donnerstag, 4. März 2010                        2
Why Node?



Donnerstag, 4. März 2010               3
Why?

                           Node's goal is to provide an easy
                           way to build scalable network
                           programs.
                                                   -- nodejs.org




Donnerstag, 4. März 2010                                           4
How?

                           Keep slow operations from
                           blocking other operations.




Donnerstag, 4. März 2010                                5
Traditional I/O

                           var data = file.read('file.txt');
                           doSomethingWith(data);




                             Something is not right here


Donnerstag, 4. März 2010                                       6
Traditional I/O

                           var data = file.read('file.txt');

                           // zzzZZzzz   FAIL!
                           doSomethingWith(data);




                              Don’t waste those cycles!


Donnerstag, 4. März 2010                                       7
Async I/O

             file.read('file.txt', function(data) {
               doSomethingWith(data);
             });                                   WIN     ✔
             doSomethingElse();




                           No need to wait for the disk,
                           do something else meanwhile!

Donnerstag, 4. März 2010                                       8
The Present



Donnerstag, 4. März 2010                 9
Quality components

                    • V8 (developed for google chrome)

                    • libev (event loop)

                    • libeio (non-block posix, thread pool)
Donnerstag, 4. März 2010                                      10
CommonJS Modules
            hello.js
             exports.world = function() {
                return 'Hello World';
             };

            main.js
             var hello = require('./hello');
             var sys = require('sys');
             sys.puts(hello.world());


                                $ node main.js
                                Hello World

Donnerstag, 4. März 2010                         11
Child processes
            child.js
             var child = process.createChildProcess('sh',
             ['-c', 'echo hello; sleep 1; echo world;']);
             child.addListener('data', function (chunk) {
               p(chunk);
             });

                              $ node child.js
                              "hellon"
                              # 1 sec delay
                              "worldn"
                              null

Donnerstag, 4. März 2010                                    12
Http Server
 var http = require('http');
 http.createServer(function(req, res) {
   setTimeout(function() {
     res.writeHeader(200, {'Content-Type': 'text/plain'});
     res.write('Thanks for waiting!');
     res.close();
   }, 1000);
 }).listen(4000);

                           $ curl localhost:4000
                           # 1 sec delay
                           Thanks for waiting!

Donnerstag, 4. März 2010                                 13
Tcp Server
              var tcp = require('tcp');
              tcp.createServer(function(socket) {
                socket.addListener('connect', function() {
                  socket.write("Hi, How Are You?n> ");
                });
                socket.addListener('data', function(data) {
                  socket.write(data);
                });
              }).listen(4000);

                            $ nc localhost 4000
                            Hi, How Are You?
                            > Great!
                            Great!
Donnerstag, 4. März 2010                                      14
DNS
          dns.js
           var dns = require('dns');
           dns.resolve4('nodejs.org', function(err, addr, ttl,
           cname) {
            p(addr, ttl, cname);
           });


                           $ node dns.js
                           [ '97.107.132.72' ]
                           84279
                           'nodejs.org'

Donnerstag, 4. März 2010                                         15
Watch File
             watch.js
              process.watchFile(__filename, function() {
                puts('You changed me!');
                process.exit();
              });



                              $ node watch.js
                              # edit watch.js
                              You changed me!

Donnerstag, 4. März 2010                                   16
ECMAScript 5
                    • Getters / setters
                      var a = {};
                      a.__defineGetter__('foo', function() {
                        return 'bar';
                      });
                      puts(a.foo);


                     • Array: filter, forEach, reduce, etc.

                     • JSON.stringify(), JSON.parse()          & more [1]
Donnerstag, 4. März 2010                                                    17
There is only 1 thread
             file.read('file.txt', function(data) {
               // Will never fire
             });

             while (true) {
               // this blocks the entire process
             }


                           Good for conceptual simplicity
                           Bad for CPU-bound algorithms

Donnerstag, 4. März 2010                                    18
The Future



Donnerstag, 4. März 2010                19
Web workers
                    • Multiple node processes that do
                           interprocess communication


                    • CPU-bound algorithms can run separately

                    • Multiple CPU cores can be used efficiently
Donnerstag, 4. März 2010                                          20
Streams

                • Node is working towards a unified data
                           stream interface


                • Stream can be readable, writable or both

                                                             see [2]
Donnerstag, 4. März 2010                                           21
Readable Streams

                • events: ‘data’, ‘end’

                • methods: pause(), resume()


Donnerstag, 4. März 2010                       22
Writeable Streams

                • events: ‘drain’, ‘close’

                • methods: write(), close()


Donnerstag, 4. März 2010                       23
Stream Redirection
    http.createServer(function (req, res) {
      // Open writable file system
      var temp = fs.openTemporaryFile();
      // Pump the request into the temp file.
      stream.pump(req, temp, function (err) {
        if (err) throw err;

        p('sweet!');
      });
    });




Donnerstag, 4. März 2010                        24
Better Socket Support

               • Support for unix sockets, socketpair(), pipe()

               • Pass sockets between processes ➠ load
                       balance requests between web workers




Donnerstag, 4. März 2010                                          25
Debugger
                • V8 support debugging

                • Node has a few bugs with exposing the
                           debugger, those need fixing


                • Command line node-debug REPL tool
Donnerstag, 4. März 2010                                  26
Readline and Curses
                • Bindings for JavaScript

                • Would allow to build better command line
                           tools


                • Goal should be to write a screen clone in
                           node


Donnerstag, 4. März 2010                                      27
HTML and XML parsing
                • HTML is a major protocol

                • Node should be able to parse dirty XML/
                           HTML


                • Should be a SAX-style parser in pure JS
Donnerstag, 4. März 2010                                    28
Support for Windows


                • Patches welcome! : )



Donnerstag, 4. März 2010                     29
Hot code reloading
                                   (maybe)



                • Reload module during runtime

                • Update code without taking server offline


Donnerstag, 4. März 2010                                     30
Suitable Applications

                    • Web frameworks

                    • Real time

                    • Crawlers

Donnerstag, 4. März 2010                           31
More Applications

                    • Process monitoring

                    • File uploading

                    • Streaming

Donnerstag, 4. März 2010                       32
Let’s write a chat



Donnerstag, 4. März 2010                        33
Http Chat in 14 LoC
    var
      http = require('http'),
      messages = [];

    http.createServer(function(req, res) {
      res.writeHeader(200, {'Content-Type' : 'text/plain'});
      if (req.url == '/') {
        res.write(messages.join("n"));
      } else if (req.url !== '/favicon.ico') {
        messages.push(decodeURIComponent(req.url.substr(1)));
        res.write('ok!');
      }
      res.close();
    }).listen(4000);

Donnerstag, 4. März 2010                                        34
Production ready?

                    • For small systems, yes.

                    • Perfect example: Comet server

                    • Usually few bugs, but API is still changing

Donnerstag, 4. März 2010                                            35
Questions?




       ✎             @felixge
       $             http://debuggable.com/
Donnerstag, 4. März 2010                      36
Links
          [1]: http://wiki.github.com/ry/node/ecma-5mozilla-
          features-implemented-in-v8
          [2]: http://wiki.github.com/ry/node/streams




Donnerstag, 4. März 2010                                       37
Bonus Slides!



Donnerstag, 4. März 2010                   38
Dirty



                    JavaScript Views            Memory Store
                    Disk Persistence            Speed > Safety


                                        Dirty


Donnerstag, 4. März 2010                                         39
A scriptable key-value store

    • Let your business logic and your data share the same
            memory / process


    • Network = OVERHEAD - Avoid whenever possible

    • V8 makes it very fast
Donnerstag, 4. März 2010                                     40
How fast?

                   • Set: 3-5 million docs / sec

                   • Get: 40-50 million docs / sec

                           (on my laptop - your milage may vary)
Donnerstag, 4. März 2010                                           41
Benchmarks


                           Do your own!



Donnerstag, 4. März 2010                  42
Disk persistence
               • Append-only log

               • Writes happen every x-Sec or every x-
                      Records


               • Callbacks fire after disk write succeeded
Donnerstag, 4. März 2010                                    43
Dirty Hello World
           hello.js
           var
             Dirty = require('dirty').Dirty,
             posts = new Dirty('test.dirty');

           posts.add({hello: 'dirty world!'});
           posts.set('my-key', {looks: 'nice'});


                     $ node hello.js
                     $ cat test.dirty
                     {"hello":"dirty world!","_key":"3b8f86..."}
                     {"looks":"nice","_key":"my-key"}

Donnerstag, 4. März 2010                                           44
Reloading from Disk
           hello.js
           var
             Dirty = require('dirty').Dirty,
             posts = new Dirty('test.dirty');

           posts.load(function() {
             p(posts.get('my-key'));
           });



                            $ node hello.js
                            {"looks": "nice", "_key": "my-key"}


Donnerstag, 4. März 2010                                          45
Use Cases

                    • Small projects (db < memory)

                    • Rapid prototyping

                    • Add HTTP/TCP interface and scale

Donnerstag, 4. März 2010                                 46
http://github.com/felixge/node-dirty



                              (or google for “dirty felixge”)



Donnerstag, 4. März 2010                                          47

Node.js - A Quick Tour II

  • 1.
    node.js A quick tour by Felix Geisendörfer Donnerstag, 4. März 2010 1
  • 2.
    Who is talking? • node.js hacker • Cofounder of Debuggable • CakePHP core alumnus Donnerstag, 4. März 2010 2
  • 3.
  • 4.
    Why? Node's goal is to provide an easy way to build scalable network programs. -- nodejs.org Donnerstag, 4. März 2010 4
  • 5.
    How? Keep slow operations from blocking other operations. Donnerstag, 4. März 2010 5
  • 6.
    Traditional I/O var data = file.read('file.txt'); doSomethingWith(data); Something is not right here Donnerstag, 4. März 2010 6
  • 7.
    Traditional I/O var data = file.read('file.txt'); // zzzZZzzz FAIL! doSomethingWith(data); Don’t waste those cycles! Donnerstag, 4. März 2010 7
  • 8.
    Async I/O file.read('file.txt', function(data) { doSomethingWith(data); }); WIN ✔ doSomethingElse(); No need to wait for the disk, do something else meanwhile! Donnerstag, 4. März 2010 8
  • 9.
  • 10.
    Quality components • V8 (developed for google chrome) • libev (event loop) • libeio (non-block posix, thread pool) Donnerstag, 4. März 2010 10
  • 11.
    CommonJS Modules hello.js exports.world = function() { return 'Hello World'; }; main.js var hello = require('./hello'); var sys = require('sys'); sys.puts(hello.world()); $ node main.js Hello World Donnerstag, 4. März 2010 11
  • 12.
    Child processes child.js var child = process.createChildProcess('sh', ['-c', 'echo hello; sleep 1; echo world;']); child.addListener('data', function (chunk) { p(chunk); }); $ node child.js "hellon" # 1 sec delay "worldn" null Donnerstag, 4. März 2010 12
  • 13.
    Http Server varhttp = require('http'); http.createServer(function(req, res) { setTimeout(function() { res.writeHeader(200, {'Content-Type': 'text/plain'}); res.write('Thanks for waiting!'); res.close(); }, 1000); }).listen(4000); $ curl localhost:4000 # 1 sec delay Thanks for waiting! Donnerstag, 4. März 2010 13
  • 14.
    Tcp Server var tcp = require('tcp'); tcp.createServer(function(socket) { socket.addListener('connect', function() { socket.write("Hi, How Are You?n> "); }); socket.addListener('data', function(data) { socket.write(data); }); }).listen(4000); $ nc localhost 4000 Hi, How Are You? > Great! Great! Donnerstag, 4. März 2010 14
  • 15.
    DNS dns.js var dns = require('dns'); dns.resolve4('nodejs.org', function(err, addr, ttl, cname) { p(addr, ttl, cname); }); $ node dns.js [ '97.107.132.72' ] 84279 'nodejs.org' Donnerstag, 4. März 2010 15
  • 16.
    Watch File watch.js process.watchFile(__filename, function() { puts('You changed me!'); process.exit(); }); $ node watch.js # edit watch.js You changed me! Donnerstag, 4. März 2010 16
  • 17.
    ECMAScript 5 • Getters / setters var a = {}; a.__defineGetter__('foo', function() { return 'bar'; }); puts(a.foo); • Array: filter, forEach, reduce, etc. • JSON.stringify(), JSON.parse() & more [1] Donnerstag, 4. März 2010 17
  • 18.
    There is only1 thread file.read('file.txt', function(data) { // Will never fire }); while (true) { // this blocks the entire process } Good for conceptual simplicity Bad for CPU-bound algorithms Donnerstag, 4. März 2010 18
  • 19.
  • 20.
    Web workers • Multiple node processes that do interprocess communication • CPU-bound algorithms can run separately • Multiple CPU cores can be used efficiently Donnerstag, 4. März 2010 20
  • 21.
    Streams • Node is working towards a unified data stream interface • Stream can be readable, writable or both see [2] Donnerstag, 4. März 2010 21
  • 22.
    Readable Streams • events: ‘data’, ‘end’ • methods: pause(), resume() Donnerstag, 4. März 2010 22
  • 23.
    Writeable Streams • events: ‘drain’, ‘close’ • methods: write(), close() Donnerstag, 4. März 2010 23
  • 24.
    Stream Redirection http.createServer(function (req, res) { // Open writable file system var temp = fs.openTemporaryFile(); // Pump the request into the temp file. stream.pump(req, temp, function (err) { if (err) throw err; p('sweet!'); }); }); Donnerstag, 4. März 2010 24
  • 25.
    Better Socket Support • Support for unix sockets, socketpair(), pipe() • Pass sockets between processes ➠ load balance requests between web workers Donnerstag, 4. März 2010 25
  • 26.
    Debugger • V8 support debugging • Node has a few bugs with exposing the debugger, those need fixing • Command line node-debug REPL tool Donnerstag, 4. März 2010 26
  • 27.
    Readline and Curses • Bindings for JavaScript • Would allow to build better command line tools • Goal should be to write a screen clone in node Donnerstag, 4. März 2010 27
  • 28.
    HTML and XMLparsing • HTML is a major protocol • Node should be able to parse dirty XML/ HTML • Should be a SAX-style parser in pure JS Donnerstag, 4. März 2010 28
  • 29.
    Support for Windows • Patches welcome! : ) Donnerstag, 4. März 2010 29
  • 30.
    Hot code reloading (maybe) • Reload module during runtime • Update code without taking server offline Donnerstag, 4. März 2010 30
  • 31.
    Suitable Applications • Web frameworks • Real time • Crawlers Donnerstag, 4. März 2010 31
  • 32.
    More Applications • Process monitoring • File uploading • Streaming Donnerstag, 4. März 2010 32
  • 33.
    Let’s write achat Donnerstag, 4. März 2010 33
  • 34.
    Http Chat in14 LoC var http = require('http'), messages = []; http.createServer(function(req, res) { res.writeHeader(200, {'Content-Type' : 'text/plain'}); if (req.url == '/') { res.write(messages.join("n")); } else if (req.url !== '/favicon.ico') { messages.push(decodeURIComponent(req.url.substr(1))); res.write('ok!'); } res.close(); }).listen(4000); Donnerstag, 4. März 2010 34
  • 35.
    Production ready? • For small systems, yes. • Perfect example: Comet server • Usually few bugs, but API is still changing Donnerstag, 4. März 2010 35
  • 36.
    Questions? ✎ @felixge $ http://debuggable.com/ Donnerstag, 4. März 2010 36
  • 37.
    Links [1]: http://wiki.github.com/ry/node/ecma-5mozilla- features-implemented-in-v8 [2]: http://wiki.github.com/ry/node/streams Donnerstag, 4. März 2010 37
  • 38.
  • 39.
    Dirty JavaScript Views Memory Store Disk Persistence Speed > Safety Dirty Donnerstag, 4. März 2010 39
  • 40.
    A scriptable key-valuestore • Let your business logic and your data share the same memory / process • Network = OVERHEAD - Avoid whenever possible • V8 makes it very fast Donnerstag, 4. März 2010 40
  • 41.
    How fast? • Set: 3-5 million docs / sec • Get: 40-50 million docs / sec (on my laptop - your milage may vary) Donnerstag, 4. März 2010 41
  • 42.
    Benchmarks Do your own! Donnerstag, 4. März 2010 42
  • 43.
    Disk persistence • Append-only log • Writes happen every x-Sec or every x- Records • Callbacks fire after disk write succeeded Donnerstag, 4. März 2010 43
  • 44.
    Dirty Hello World hello.js var Dirty = require('dirty').Dirty, posts = new Dirty('test.dirty'); posts.add({hello: 'dirty world!'}); posts.set('my-key', {looks: 'nice'}); $ node hello.js $ cat test.dirty {"hello":"dirty world!","_key":"3b8f86..."} {"looks":"nice","_key":"my-key"} Donnerstag, 4. März 2010 44
  • 45.
    Reloading from Disk hello.js var Dirty = require('dirty').Dirty, posts = new Dirty('test.dirty'); posts.load(function() { p(posts.get('my-key')); }); $ node hello.js {"looks": "nice", "_key": "my-key"} Donnerstag, 4. März 2010 45
  • 46.
    Use Cases • Small projects (db < memory) • Rapid prototyping • Add HTTP/TCP interface and scale Donnerstag, 4. März 2010 46
  • 47.
    http://github.com/felixge/node-dirty (or google for “dirty felixge”) Donnerstag, 4. März 2010 47