Book Image

Mastering Node.js

By : Sandro Pasquali
Book Image

Mastering Node.js

By: Sandro Pasquali

Overview of this book

Node.js is a modern development stack focused on providing an easy way to build scalable network software. Backed by a growing number of large companies and a rapidly increasing developer base, Node is revolutionizing the way that software is being built today. Powered by Google's V8 engine and built out of C++ modules, this is a JavaScript environment for the enterprise.Mastering Node.js will take the reader deep into this exciting development environment. Beginning with a comprehensive breakdown of its innovative non-blocking evented design, Node's structure is explained in detail, laying out how its blazingly fast I/O performance simplifies the creation of fast servers, scalable architectures, and responsive web applications.Mastering Node.js takes you through a concise yet thorough tour of Node's innovative evented non-blocking design, showing you how to build professional applications with the help of detailed examples.Learn how to integrate your applications with Facebook and Twitter, Amazon and Google, creating social apps and programs reaching thousands of collaborators on the cloud. See how the Express and Path frameworks make the creation of professional web applications painless. Set up one, two, or an entire server cluster with just a few lines of code, ready to scale as soon as you're ready to launch. Move data seamlessly between databases and file systems, between clients, and across network protocols, using a beautifully designed, consistent, and predictable set of tools.Mastering Node.js contains all of the examples and explanations you'll need to build applications in a short amount of time and at a low cost, running on a scale and speed that would have been nearly impossible just a few years ago.
Table of Contents (20 chapters)
Mastering Node.js
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

V8


V8 is Google's JavaScript engine, written in C++. It compiles and executes JavaScript code inside of a VM (Virtual Machine). When a webpage loaded into Google Chrome demonstrates some sort of dynamic effect, like automatically updating a list or news feed, you are seeing JavaScript, compiled by V8, at work.

While Node itself will efficiently manage I/O operations, its process object refers to the V8 runtime. As such, it is important to understand how to configure the V8 environment, especially as your application grows in size.

By typing node -h into a console, something like the following will be displayed:

We can see how a list of V8 options is accessible via the –-v8-options flag.

The list of configuration options for V8 is a long one, so we're not going to cover each option here. As we progress through the book, relevant options will be discussed with more depth. It is nevertheless useful to summarize some of the options provided for managing system limits and memory, as well as those used to configure JavaScript's command set, introducing some of the new features in ES6 (EcmaScript6), often referred to as Harmony.

The version of V8 used by your Node installation can be viewed by typing:

node –e "console.log(process.versions.v8)"

Memory and other limits

One very powerful V8 configuration option is important enough to make it into Node's own collection: --max-stack-size. Let's look into some of the new powers a Node developer has been given in being able to configure a specific JavaScript runtime.

Trying to break a system is an excellent way to discover its limits and shape. Let's write a program that will crash V8:

var count = 0;
(function curse() { 
  console.log(++count);
  curse();
})()

This self-contained, self-executing function will recursively call itself forever, or until it is forced to stop. Each iteration of curse adds another frame to the call stack. This uncontrolled growth will eventually cause the JavaScript runtime to collapse, citing a RangeError: Maximum call stack size exceeded.

The purpose of --max-stack-size should now be clear. The direct V8 option equivalent is –-stack_size, which is passed a value, in KB (Kilobytes), to raise this limit. Experiment with the above program, noting the number of iterations possible at different settings.

While it is likely that hitting this limit represents an incorrectly designed algorithm, being able to expand the width of the operating space available to a Node process adds to the collection of solutions available to developers.

On 32 bit and 64 bit machines V8's memory allocation defaults are, respectively, 700 MB and 1400 MB. In newer versions of V8, memory limits on 64 bit systems are no longer set by V8, theoretically indicating no limit. However, the OS (Operating System) on which Node is running can always limit the amount of memory V8 can take, so the true limit of any given process cannot be generally stated.

V8 makes available the --max_old_space_size option, which allows control over the amount of memory available to a process, accepting a value in MB. Should you need to increase memory allocation, simply pass this option the desired value when spawning a Node process.

It is often an excellent strategy to reduce the available memory allocation for a given Node instance, especially when running many instances. As with stack limits, consider whether massive memory needs are better delegated to a dedicated storage layer, such as an in-memory database or similar.

Note

An informative discussion with the V8 team regarding their views on how memory should be allocated can be found here:

http://code.google.com/p/v8/issues/detail?id=847

One of the key advantages of modern high-level languages such as JavaScript is the automatic management of memory through GC (Garbage Collection). GC strategies are many and complex, yet all follow a simple core idea: every so often, free allocated memory that is no longer being used.

The drawback of automatic GC is that it puts a slight brake on process speed. While the clear advantages of automatic GC outweigh its drawbacks in the majority of cases, there remains for the Node developer an opportunity to control some of its behavior. This is primarily done via the flags –-nouse_idle_notification and –-expose_gc.

Passing the –-nouse_idle_notification flag will tell V8 to ignore idle notification calls from Node, which are requests to V8 asking it to run GC immediately, as the Node process is currently idle. Because Node is aggressive with these calls (efficiency breeds clean slates), an excess of GC may slow down your application. Note that using this flag does not disable GC; GC simply runs less often. In the right circumstances this technique can increase performance.

--expose_gc introduces a new global method to the Node process, gc(), which allows JavaScript code to manually start the GC process. In conjunction with –-nouse_idle_notification the developer can now control to some degree how often GC runs. At any point in my JavaScript code I can simply call gc() and start the collector.

Being able to adjust memory usage and GC is certainly useful. Remember that application volume can rapidly rise in unpredictable ways. If the memory footprint of your application holds steady near the very limits of V8's allocation, you should begin to think about scaling horizontally. Use memory wisely, and split off new Node instances where appropriate.

Harmony

JavaScript has never stopped evolving and it is now experiencing something of a renaissance, helped in no small part by the popularity of Node. The language's next version, named Harmony, introduces some significant new features and concepts.

Note

More information on ES6 Harmony can be found at: http://wiki.ecmascript.org/doku.php?id=harmony:harmony.

The available Harmony options are:

Flag

Description

--harmony_typeof

Enable semantics for typeof

--harmony_scoping

Enable block scoping

--harmony_modules

Enable modules (implies block scoping)

--harmony_proxies

Enable proxies

--harmony_collections

Enable collections (sets, maps, and weak maps)

--harmony

Enable all features (except typeof)

It is beyond the scope of this book to discuss these new features in any depth. Nonetheless, it should be stated that this ability to use the very latest JavaScript features, now, through Node, offers the developer a great advantage—there is no browser war on a server to hold back innovation.

For example, ES6's weakMap allows the use of non-strings as keys in a HashMap:

"use strict"
let owners = new WeakMap();
let task = {
  title 	: "Big Project"
};
owners.set(task, 'John');
function owner(task) {
  if(owners.has(task)) {
    return console.log(owners.get(task));
  }
  console.log("No owner for this task.");
}
owner(task);   // "John"
owner({});   // "No owner for this task"

As an exercise, the reader might map (fixed) input streams to (variable) output streams in a similar manner.