DailyJS

DailyJS

The JavaScript blog.


Tagbenchmarking
Featured

node modules http npm benchmarking

Node Roundup: 0.10.17, Defining Global Scripts in npm, loadtest

Posted on .

Node 0.10.17

Node 0.10.17 is out, so it seems like we're back to weekly releases again. This version updates uv, tls, stream, dgram, and readline. The stream module fix makes errors raise exceptions when 'error' listeners are removed, which seems like a slight oversight to me...

Defining Global Scripts in npm

Joe Sullivan sent in his post about how global scripts are defined in popular npm modules. This is the kind of thing I like to see -- learning from the pros. Joe summarises the common approaches at the end of the post.

loadtest

loadtest (GitHub: alexfernandez / loadtest, License: MIT, npm: loadtest) by Alex Fernández is a load testing module inspired by and partly compatible with Apache ab. It can be invoked as a command-line script or used as a module.

var loadtest = require('loadtest');  
var options = {  
    url: 'http://localhost:8000',
    maxRequests: 1000,
};

loadtest.loadTest(options, function(error, result) {  
  if (error) {
    return console.error('Error:', error);
  }

  console.log('Tests run successfully');
});

The callback is run when the requests have been made, or the specified number of seconds have elapsed.

Featured

libraries node security search benchmarking

localStorage DOS, Lunr.js, Vlug

Posted on .

localStorage DOS

Even though the Web Storage specification says user agents should limit the amount of space used to store data, a new exploit uses it to store gigabytes of junk. The exploit is based around storing data per-subdomain, which gets around the limits most browsers have already implemented. Users testing it found Chrome would crash when run in incognito mode, but Firefox was immune to the attack.

Other security researchers have raised concerns about localStorage in the past. Joey Tyson talked about storing malicious code in localStorage, and Todd Anglin wrote about some of the more obscure facts about localStorage which touches on security.

Lunr.js

Oliver Nightingale from New Bamboo sent in his extremely well-presented full-text browser-based search library (GitHub: olivernn / lunr.js, License: MIT), which indexes JSON documents using some of the core techniques of larger server-side full-text search engines: tokenising, stemming, and stop word removal.

By removing the need of extra server side processes, search can be a feature on sites or apps that otherwise would not have warranted the extra complexity.

Trie is used for mapping tokens to matching documents, so if you're interested in JavaScript implementations of data structures then take a look at the source. The source includes tests and benchmarks, and a build script so you can generate your own builds.

Vlug

Vlug (GitHub: pllee / vlug, License: MIT, npm: vlug) by Patrick Lee is a small instrumentation library for benchmarking code without manually adding log statements. The Vlug.Interceptor object takes a specification of things to log, which will dynamically invoke calls to console.time and console.timeEnd to collect benchmarks.

Patrick has tested it with browsers and Node, and has included Vlug.Runner for running iterations on functions. The readme and homepage both have documentation and examples.

Featured

node benchmarking raspberry-pi hardware

Node Roundup: Knockout Winners, Node for Raspberry Pi, Benchtable

Posted on .

You can send in your Node projects for review through our contact form or @dailyjs.

Node.js Knockout Winners Announced

Disasteroids

Node.js Knockout had an outstanding 167 entries this year. The overall winner was Disasteroids by SomethingCoded. It's an original take on several arcade classics: imagine a multiplayer version of Asteroids crossed with the shooting mechanics of Missile Command, but with projectiles that are affected by gravity.

The other winners are currently listed on the site, but I've reproduced them here to give the entrants more well-earned kudos:

Congratulations to all the winners, and be sure to browse the rest of the entries for hours of fun!

Node on Raspberry Pi

Node Pi

If you've got a Raspberry Pi you probably already know it's possible to run Node on the ARM-based tiny computer. If not then Node.js Debian package for ARMv5 by Vincent Rabah explains how to get Node running with his custom Debian package.

"But the Raspberry Pi is just a cheap computer, what's so great about it?" I hear you cry in the comments. There's an intrinsic value to the Raspberry Pi Foundation's efforts in making such hardware suitable for school children. No offence to Microsoft, but in a country where Office was on the curriculum for "IT" we can use any help we can get aiding the next generation of hackers and professional engineers.

Benchtable

Benchtable

I love the command-line, it's where I write code, DailyJS, notes, email -- colourful text and ancient Unix utilities abound. But, I also like to fiddle with the way things look. For example, if I'm writing benchmarks I don't want to just print them out in boring old monochrome text, I want them to look cool.

Ivan Zuzak's Benchtable (License: Apache 2.0, npm: benchtable) is built for just such a need. It prints benchmarks in tables, making it a little bit easier to compare values visually. It's built on Benchmark.js, which is one of the most popular benchmarking modules.

The API is based around the Benchtable prototype which is based on Benchmark.Suite, so it can be dropped into an existing benchmarking suite without too much effort.

Featured

performance node ES5 Enumeration ES3 benchmarking maintainability

JavaScript for Node Part 1: Enumeration

Posted on .

JavaScript developers have been accustomed to a very scattered and incoherent API (the DOM) for some time. As a result, some of JavaScript's most common patterns are pretty weird and unnecessary when programming for a unified and coherent API like Node. It can be easy to forget that the entire ES5 specification is available to you, but there are some standard patterns that deserve to be rethought because of ES5's newer features.

Objects in ES5

Since no object in JavaScript can have identical same-tier keys, all objects can be thought of as being hash tables. Indeed, V8 implements a hash function for object keys. This important concept did not go unnoticed in the ES5 draft and so the method Object.keys was created to extract the internal associative array of any object and return it as a JavaScript Array. In layman's terms, this means that Object.keys returns only the keys that belong to that object and NOT any properties that it may have inherited. This is a powerful and useful construct that can be utilized in Node when enumerating over an object.

The Old Way

Chances are you have run into the following looping pattern:

var key;  
for (key in obj) {  
  if (obj.hasOwnProperty(key))
    obj[key];
}

This was the only way to traverse an object in ES3 without going up an object's prototype chain.

A Better Way

In ES5 there is a better approach. Given that we can simply get the keys of an object and put them into an array, we can loop over an object, but only at the cost of looping over an array. First consider the following:

var keys = Object.keys(obj), i, l;

for (i = 0, l = keys.length; i < l; i++)  
  obj[keys[i]];

This is usually the fastest way of looping over an object in ES5 (at least in V8). However, this method has some drawbacks. If new variables are needed to make calculations, this approach starts to feel overly verbose. Consider the following:

function calculateAngularDistanceOfObject(obj) {  
  if (typeof obj !== 'object') return;
  var keys = Object.keys(obj),
    , EARTH_RADIUS = 3959
    , RADIAN_CONST = Math.PI / 180
    , deltaLat
    , deltLng
    , halfTheSquareChord
    , angularDistanceRad
    , temp
    , a, b, i, l
    ;

  for (i = 0, l = keys.length; i < l; i++) {
    temp = obj[keys[i]];
    a = temp.a;
    b = temp.b;
    deltaLat = a.subLat(b) * RADIAN_CONST;
    deltaLng = a.subLng(b) * RADIAN_CONST;
    halfTheSquareChord = Math.pow(Math.sin(deltaLat / 2), 2) + Math.pow(Math.sin(deltaLng / 2), 2) * Math.cos(a.lat * RADIAN_CONST) * Math.cos(b.lat * RADIAN_CONST);
    obj[keys[i]].angularDistance = 2 * Math.atan2(Math.sqrt(halfTheSquareChord), Math.sqrt(1 - halfTheSquareChord));
  }
}

An Even Better Way

In situations like this, instead of looping over the array of keys using Array’s native forEach method will allow us to create a new scope for the variables we are working with. This will allow us to do our processing in a more encapsulated manner:

function calculateAngularDistanceOfObject(obj) {  
  if (typeof obj !== 'object') return;

  var EARTH_RADIUS = 3959
    , RADIAN_CONST = Math.PI / 180;

  Object.keys(obj).forEach(function(key) {
    var temp = obj[key]
      , a = temp.a
      , b = temp.b
      , deltaLat = a.subLat(b) * RADIAN_CONST
      , deltaLng = a.subLng(b) * RADIAN_CONST;

    halfTheSquareChord = Math.pow(Math.sin(deltaLat / 2), 2) + Math.pow(Math.sin(deltaLng / 2), 2) * Math.cos(a.lat * RADIAN_CONST) * Math.cos(b.lat * RADIAN_CONST);
    obj[key].angularDistance =  2 * Math.atan2(Math.sqrt(halfTheSquareChord), Math.sqrt(1 - halfTheSquareChord));
  });
}

Benchmarking

Choosing the right pattern depends on balancing maintainability with performance. Of the two patterns, forEach is generally considered more readable. In general, iterating over large arrays will generally perform worse with forEach (although better than the old ES3 way), but it's important to correctly benchmark code before making a decision.

One popular solution for Node is node-bench (npm: bench) written by Isaac Schlueter. After installing it here is something to start with:

var bench = require('bench')  
  , obj = { zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9 };

// This is to simulate the object having non-enumerable properties
Object.defineProperty(obj, 'z', { value: 26, enumerable: false });

exports.compare = {  
  'old way': function() {
    for (var name in obj) {
      if (obj.hasOwnProperty(name))
        obj[name];
    }
  },

  'loop array': function() {
    var keys = Object.keys(obj)
      , i
      , l;

    for (i = 0, l = keys.length; i < l; i++)
      obj[keys[i]];
  },

  'foreach loop': function() {
    Object.keys(obj).forEach(function(key) {
      obj[key];
    });
  }
};

// This is number of iterations on each test we want to run
bench.COMPARE_COUNT = 8;  
bench.runMain();