From 456bb1b9f81b7253b6339272eb11df371cb42216 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 18 May 2009 23:21:11 +0200 Subject: [PATCH] Work on motivation statement. --- website/node.html | 134 ++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 75 deletions(-) diff --git a/website/node.html b/website/node.html index 71cfa866ba..d62f3f9995 100644 --- a/website/node.html +++ b/website/node.html @@ -31,6 +31,7 @@ body { #toc a { color: #777; } h1, h2, h3, h4 { + color: #B0C4DE; margin: 2em 0; } @@ -39,8 +40,8 @@ h1 a { color: inherit; } pre, code { font-family: monospace; - font-size: 13pt; - color: #bab; + font-size: 14pt; + color: #dcd; } pre { @@ -83,9 +84,9 @@ a:hover { text-decoration: underline; }
  • API
    1. Timers -
    2. File System -
    3. tcp -
    4. http +
    5. File System I/O +
    6. TCP +
    7. HTTP
      1. Server
      2. ServerRequest @@ -121,88 +122,73 @@ class="sh_javascript">setTimeout() nor listen(8000). -File I/O is also preformed without blocking. In fact, not a single function in Node blocks execution. -There isn't even a call to run the event loop. - -

        Programmers using this environment will find it difficult to design -their systems ineffiencely. It's impossible to make a database call from a -web server and block other requests. +

        Programming in Node is different. Instead of commanding actions, Node +scripts defining behaviors. The entire program is centered around I/O +events.

        Check out the API documentation for more examples.

        Node is free to download, use, and build upon.

        -

        Motivation

        - -

        Evented Programming Makes More Sense

        - -Difference between blocking/non-blocking design -

        There are many methods to write internet servers but they can -fundamentally be divided into two camps: evented and threaded; non-blocking -and blocking. A blocking server accepts a connection and launches a new -thread to handle the connection. Because the concurrency is handled by -the thread scheduler, a blocking server can make function calls which -preform full network requests. -

        var response = db.execute("SELECT * FROM table");
        -// do something
        - -

        An evented server manages its concurrency itself. All connections -are handled in a single thread and callbacks are executed on certain -events: "socket 23 is has data to read", "socket 65's write buffer is -empty". An evented server executes small bits of code but never -blocks the process. In the evented world callbacks are used -instead of functions - -

        db.execute("SELECT * FROM table", function (response) {
        -  // do something
        -});
        +

        Motivation

        +

        +I/O is hard and almost no one gets it right. +This is an attempt to make you to do it right by taking away all those +sharp, dangerous tools called threads. + +

        +Node is forced evented programming—so by default you are doing the +right thing. +Well, actually, Javascript +itself is forced evented programming. Node brings Javascript, in the way +it was meant to be, out of the browser. + +

        +There +is a major difference in the latency between memory and disk I/O. It looks +approximately like this: -

        I/O latency

        -l1 cache ~ 3
        +l1 cache ~ 3          (CPU cycles)
         l2 cache ~ 14
              ram ~ 250
             disk ~ 41000000
          network ~ 240000000
         
        -

        purely evented interfaces rule out a lot of stupidity +

        Disk and network I/O need to be treated differently than simple memory +operations. But POSIX obscures the latency with system calls like + +

        close(file_descriptor);
        + +

        For a TCP file descriptor, this is a round trip message to a remote +computer that can cost billions of CPU cycles. For a hard drive file descriptor, +close() could mean a couple million cycles of disk spinning. +The man pages don't even mention that a call might be preforming very +long I/O operations. This ambiguity in POSIX is propagated into higher APIs. + +

        In the Node API all I/O happens on the event loop and thus requires a +callback of some sort. Calls to access foreign database do not look like +simple side-effect free functions. The programmer does not need advanced +knowledge of POSIX to know that I/O is being performed because it looks +differently. + +

        Some find event programming cumbersome. +I find threaded programming +cumbersome—it's not a good abstraction of what is really happening. +Because of this bad abstraction it's confusing and difficult to get right. +Threaded programs only look good in the simpliest and most trivial +situations—in real-life applications events lead to better +architecture. -

        Evented programs are more efficient

        -
          -
        1. pthread stack size - 2mb default stack size on linux (1mb on windows, 64kb on FreeBSD) - of course this is adjustable -
        2. context switching benchmark -
        3. Apache vs. Nginx -
        4. event machine vs mongrel (neverblock) -
        -

        The appropriateness of Javascript

        -
          -
        1. No I/O -

          Javascript is without I/O. In the browser the DOM provides I/O, - but non-browser javascript interpreters have only non-standardized - functions to allow them print to console or access the network. -

        2. No Threads -
        3. Good compiler -
        4. Universality of the language -

          Contemporary computer infrastructure has two irreplaceable - languages: C and Javascript. C is the language of operating systems. - POSIX, the universal operating system API, is defined in C. So while you - can interface with operating systems in Java and Haskell, those - languages access must make system calls in C. Similarly, Javascript is - the language of the web operating system. In place of POSIX is the - DOM. You can wrap Javascript, you can compile to Javascript, but in the - end browsers must be interfaced with in Javascript. Portable low-level - systems tend to be written in C and portable web-level systems are - written in Javascript. -

        Benchmarks

        @@ -436,10 +422,10 @@ The module path does not include filename extensions like onLoad() is -provided to notify the user when all the included modules are loaded. -Each file can have its own onLoad() callback. -onLoad() will always be called exactly once for each file. +has a policy of never blocking, the callback onLoad can be set and will notify the user +when all the included modules are loaded. Each file/module can have an onLoad callback.

        To export an object, add to the special exports object. @@ -447,14 +433,12 @@ Each file can have its own onLoad() callback.

        The functions fail and deepEquals are not exported and remain private to the module. -

        In addition to include() a module can use -require(). Instead of loading the exported objects into the -global namespace, it will return a namespace object. The exported objects +

        require() is like include() except does not +polute the global namespace. It returns a namespace object. The exported objects can only be guaranteed to exist after the onLoad() callback is made. For example:

         var mjsunit = require("mjsunit");
        -
         function onLoad () {
           mjsunit.assertEquals(1, 2);
         }