KEMBAR78
Introduction to node.js
There’s no sleep()
    in Javascript

Introduction to node.js
      twitter.com/jacek_becela
           github.com/ncr
node.js
node.js
• Server-side Javascript runtime
 • Google V8
 • CommonJS modules
node.js
• Server-side Javascript runtime
 • Google V8
 • CommonJS modules
• API for highly concurrent programming
 • All I/O is non-blocking (asynchronous)
 • Achieved using Event Loop
Two approaches to I/O
// blocking I/O + threads
var urls = db.query("select * from urls"); // wait
urls.each(function (url) {
  var page = http.get(url); // wait
  save(page); // wait
});
 
// non-blocking I/O + event loop
db.query("select * from urls", function (urls) {
  urls.each(function (url) {
    http.get(url, function (page) {
      save(page);
    });
  });
});
I/O Costs




http://nodejs.org/jsconf.pdf
I/O Costs

• L1: 3 cycles




         http://nodejs.org/jsconf.pdf
I/O Costs

• L1: 3 cycles
• L2: 14 cycles



         http://nodejs.org/jsconf.pdf
I/O Costs

• L1: 3 cycles
• L2: 14 cycles
• RAM: 250 cycles


        http://nodejs.org/jsconf.pdf
I/O Costs

• L1: 3 cycles
• L2: 14 cycles
• RAM: 250 cycles
• DISK: 41,000,000 cycles

        http://nodejs.org/jsconf.pdf
I/O Costs

• L1: 3 cycles
• L2: 14 cycles
• RAM: 250 cycles
• DISK: 41,000,000 cycles
• NETWORK: 240,000,000 cycles
       http://nodejs.org/jsconf.pdf
Apache vs. Nginx




http://blog.webfaction.com/a-little-holiday-present
Apache vs. Nginx




http://blog.webfaction.com/a-little-holiday-present
Why threads are bad
Why threads are bad
• Hard to program
Why threads are bad
• Hard to program
• Shared state and locks
Why threads are bad
• Hard to program
• Shared state and locks
• Deadlocks
Why threads are bad
• Hard to program
• Shared state and locks
• Deadlocks
• Giant locks decrease concurrency
Why threads are bad
• Hard to program
• Shared state and locks
• Deadlocks
• Giant locks decrease concurrency
• Fine-grained locks increase complexity
Why threads are bad
• Hard to program
• Shared state and locks
• Deadlocks
• Giant locks decrease concurrency
• Fine-grained locks increase complexity
• Race conditions
Why threads are bad
• Hard to program
• Shared state and locks
• Deadlocks
• Giant locks decrease concurrency
• Fine-grained locks increase complexity
• Race conditions
• Context switching costs
When threads are good
When threads are good

• Support Multi-core CPUs
When threads are good

• Support Multi-core CPUs
• CPU-heavy work
When threads are good

• Support Multi-core CPUs
• CPU-heavy work
• Little or no shared state
When threads are good

• Support Multi-core CPUs
• CPU-heavy work
• Little or no shared state
• Threads count == CPU cores count
Event Loop
 user perspective
• You already use it everyday for I/O
• You register callbacks for events
• Your callback is eventually fired
      $("a").click(function () {
        console.log("clicked!");
      });
       
      $.ajax(..., function (...) {
        console.log("internets!");
      });
Event Loop
 life cycle
Event Loop
            life cycle
• Initialize empty event loop (just an array)
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
 • Execute non-I/O code
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
 • Execute non-I/O code
 • Add every I/O call to the event loop
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
 • Execute non-I/O code
 • Add every I/O call to the event loop
• End of source code reached
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
 • Execute non-I/O code
 • Add every I/O call to the event loop
• End of source code reached
• Event loop starts iterating
Event Loop
            life cycle
• Initialize empty event loop (just an array)
• Read and “execute” code
 • Execute non-I/O code
 • Add every I/O call to the event loop
• End of source code reached
• Event loop starts iterating
• All this happens in a single thread
Event Loop
 life cycle
Event Loop
             life cycle
• Iterate over a list of events and callbacks
Event Loop
             life cycle
• Iterate over a list of events and callbacks
• Perform I/O using non-blocking kernel
  facilities: epoll, kqueue, /dev/poll, select
Event Loop
             life cycle
• Iterate over a list of events and callbacks
• Perform I/O using non-blocking kernel
  facilities: epoll, kqueue, /dev/poll, select
• Event Loop goes to sleep
Event Loop
             life cycle
• Iterate over a list of events and callbacks
• Perform I/O using non-blocking kernel
  facilities: epoll, kqueue, /dev/poll, select
• Event Loop goes to sleep
• Kernel notifies the Event Loop
Event Loop
             life cycle
• Iterate over a list of events and callbacks
• Perform I/O using non-blocking kernel
  facilities: epoll, kqueue, /dev/poll, select
• Event Loop goes to sleep
• Kernel notifies the Event Loop
• Event Loop executes and removes a callback
Event Loop
             life cycle
• Iterate over a list of events and callbacks
• Perform I/O using non-blocking kernel
  facilities: epoll, kqueue, /dev/poll, select
• Event Loop goes to sleep
• Kernel notifies the Event Loop
• Event Loop executes and removes a callback
• Program exits when Event Loop is empty
Event Loop limitations
Event Loop limitations
• Callbacks have to return fast
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
• What about multi-core CPUs
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
• What about multi-core CPUs
 • Web Workers using separate processes
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
• What about multi-core CPUs
 • Web Workers using separate processes
 • Can do CPU-heavy stuff
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
• What about multi-core CPUs
 • Web Workers using separate processes
 • Can do CPU-heavy stuff
 • No shared memory - no locks
Event Loop limitations
• Callbacks have to return fast
 • No CPU-heavy stuff
• What about multi-core CPUs
 • Web Workers using separate processes
 • Can do CPU-heavy stuff
 • No shared memory - no locks
 • Communication using message passing
Hello World
var sys = require('sys'),
   http = require('http');
http.createServer(function (req, res) {
  setTimeout(function () {
    res.sendHeader(200, {'Content-Type': 'text/plain'});
    res.write('Hello World');
    res.close();
  }, 2000);
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');
sleep()
sleep()
• It is a blocking call per definition
sleep()
• It is a blocking call per definition
• Browser JS has no blocking functions
sleep()
• It is a blocking call per definition
• Browser JS has no blocking functions
• Except synchronous AJAX which is
  supposed to be used in “unload” event
sleep()
• It is a blocking call per definition
• Browser JS has no blocking functions
• Except synchronous AJAX which is
  supposed to be used in “unload” event
• You can emulate sleep() using a “while”
  loop and checking wall clock but what’s the
  point...
sleep()
• It is a blocking call per definition
• Browser JS has no blocking functions
• Except synchronous AJAX which is
  supposed to be used in “unload” event
• You can emulate sleep() using a “while”
  loop and checking wall clock but what’s the
  point...
• The real reason: JavaScript exceution and
  Event Loop live in a single thread
Where to go next
• github.com/ry/node
• groups.google.com/group/nodejs
• howtonode.org
• dailyjs.org
• search twitter for node.js
• github.com/ncr/flickr_spy
Demo

Introduction to node.js

  • 1.
    There’s no sleep() in Javascript Introduction to node.js twitter.com/jacek_becela github.com/ncr
  • 2.
  • 3.
    node.js • Server-side Javascriptruntime • Google V8 • CommonJS modules
  • 4.
    node.js • Server-side Javascriptruntime • Google V8 • CommonJS modules • API for highly concurrent programming • All I/O is non-blocking (asynchronous) • Achieved using Event Loop
  • 5.
    Two approaches toI/O // blocking I/O + threads var urls = db.query("select * from urls"); // wait urls.each(function (url) {   var page = http.get(url); // wait   save(page); // wait });   // non-blocking I/O + event loop db.query("select * from urls", function (urls) {   urls.each(function (url) {     http.get(url, function (page) {       save(page);     });   }); });
  • 6.
  • 7.
    I/O Costs • L1:3 cycles http://nodejs.org/jsconf.pdf
  • 8.
    I/O Costs • L1:3 cycles • L2: 14 cycles http://nodejs.org/jsconf.pdf
  • 9.
    I/O Costs • L1:3 cycles • L2: 14 cycles • RAM: 250 cycles http://nodejs.org/jsconf.pdf
  • 10.
    I/O Costs • L1:3 cycles • L2: 14 cycles • RAM: 250 cycles • DISK: 41,000,000 cycles http://nodejs.org/jsconf.pdf
  • 11.
    I/O Costs • L1:3 cycles • L2: 14 cycles • RAM: 250 cycles • DISK: 41,000,000 cycles • NETWORK: 240,000,000 cycles http://nodejs.org/jsconf.pdf
  • 12.
  • 13.
  • 14.
  • 15.
    Why threads arebad • Hard to program
  • 16.
    Why threads arebad • Hard to program • Shared state and locks
  • 17.
    Why threads arebad • Hard to program • Shared state and locks • Deadlocks
  • 18.
    Why threads arebad • Hard to program • Shared state and locks • Deadlocks • Giant locks decrease concurrency
  • 19.
    Why threads arebad • Hard to program • Shared state and locks • Deadlocks • Giant locks decrease concurrency • Fine-grained locks increase complexity
  • 20.
    Why threads arebad • Hard to program • Shared state and locks • Deadlocks • Giant locks decrease concurrency • Fine-grained locks increase complexity • Race conditions
  • 21.
    Why threads arebad • Hard to program • Shared state and locks • Deadlocks • Giant locks decrease concurrency • Fine-grained locks increase complexity • Race conditions • Context switching costs
  • 22.
  • 23.
    When threads aregood • Support Multi-core CPUs
  • 24.
    When threads aregood • Support Multi-core CPUs • CPU-heavy work
  • 25.
    When threads aregood • Support Multi-core CPUs • CPU-heavy work • Little or no shared state
  • 26.
    When threads aregood • Support Multi-core CPUs • CPU-heavy work • Little or no shared state • Threads count == CPU cores count
  • 27.
    Event Loop userperspective • You already use it everyday for I/O • You register callbacks for events • Your callback is eventually fired $("a").click(function () {   console.log("clicked!"); });   $.ajax(..., function (...) {   console.log("internets!"); });
  • 28.
  • 29.
    Event Loop life cycle • Initialize empty event loop (just an array)
  • 30.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code
  • 31.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code • Execute non-I/O code
  • 32.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code • Execute non-I/O code • Add every I/O call to the event loop
  • 33.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code • Execute non-I/O code • Add every I/O call to the event loop • End of source code reached
  • 34.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code • Execute non-I/O code • Add every I/O call to the event loop • End of source code reached • Event loop starts iterating
  • 35.
    Event Loop life cycle • Initialize empty event loop (just an array) • Read and “execute” code • Execute non-I/O code • Add every I/O call to the event loop • End of source code reached • Event loop starts iterating • All this happens in a single thread
  • 36.
  • 37.
    Event Loop life cycle • Iterate over a list of events and callbacks
  • 38.
    Event Loop life cycle • Iterate over a list of events and callbacks • Perform I/O using non-blocking kernel facilities: epoll, kqueue, /dev/poll, select
  • 39.
    Event Loop life cycle • Iterate over a list of events and callbacks • Perform I/O using non-blocking kernel facilities: epoll, kqueue, /dev/poll, select • Event Loop goes to sleep
  • 40.
    Event Loop life cycle • Iterate over a list of events and callbacks • Perform I/O using non-blocking kernel facilities: epoll, kqueue, /dev/poll, select • Event Loop goes to sleep • Kernel notifies the Event Loop
  • 41.
    Event Loop life cycle • Iterate over a list of events and callbacks • Perform I/O using non-blocking kernel facilities: epoll, kqueue, /dev/poll, select • Event Loop goes to sleep • Kernel notifies the Event Loop • Event Loop executes and removes a callback
  • 42.
    Event Loop life cycle • Iterate over a list of events and callbacks • Perform I/O using non-blocking kernel facilities: epoll, kqueue, /dev/poll, select • Event Loop goes to sleep • Kernel notifies the Event Loop • Event Loop executes and removes a callback • Program exits when Event Loop is empty
  • 43.
  • 44.
    Event Loop limitations •Callbacks have to return fast
  • 45.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff
  • 46.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff • What about multi-core CPUs
  • 47.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff • What about multi-core CPUs • Web Workers using separate processes
  • 48.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff • What about multi-core CPUs • Web Workers using separate processes • Can do CPU-heavy stuff
  • 49.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff • What about multi-core CPUs • Web Workers using separate processes • Can do CPU-heavy stuff • No shared memory - no locks
  • 50.
    Event Loop limitations •Callbacks have to return fast • No CPU-heavy stuff • What about multi-core CPUs • Web Workers using separate processes • Can do CPU-heavy stuff • No shared memory - no locks • Communication using message passing
  • 51.
    Hello World var sys= require('sys'),    http = require('http'); http.createServer(function (req, res) {   setTimeout(function () {     res.sendHeader(200, {'Content-Type': 'text/plain'});     res.write('Hello World');     res.close();   }, 2000); }).listen(8000); sys.puts('Server running at http://127.0.0.1:8000/');
  • 52.
  • 53.
    sleep() • It isa blocking call per definition
  • 54.
    sleep() • It isa blocking call per definition • Browser JS has no blocking functions
  • 55.
    sleep() • It isa blocking call per definition • Browser JS has no blocking functions • Except synchronous AJAX which is supposed to be used in “unload” event
  • 56.
    sleep() • It isa blocking call per definition • Browser JS has no blocking functions • Except synchronous AJAX which is supposed to be used in “unload” event • You can emulate sleep() using a “while” loop and checking wall clock but what’s the point...
  • 57.
    sleep() • It isa blocking call per definition • Browser JS has no blocking functions • Except synchronous AJAX which is supposed to be used in “unload” event • You can emulate sleep() using a “while” loop and checking wall clock but what’s the point... • The real reason: JavaScript exceution and Event Loop live in a single thread
  • 58.
    Where to gonext • github.com/ry/node • groups.google.com/group/nodejs • howtonode.org • dailyjs.org • search twitter for node.js • github.com/ncr/flickr_spy
  • 60.