I want to share with you a very interesting optimization technique in Javascript.

Let's consider a hypothetical situation. Suppose we have a stack of servers that, at any given time, by their internal whim, may be able to “ok” or “down”. The server interface allows you to find out only its name and current status. But how is the server, and where it comes from we do not know, we do not have access to it. Let this code be the constructor for our servers:
var Server = function(name){ this.name = name; this.ping = function(){return Math.round(Math.random())? 'ok' : 'down';}; };
Suppose there is a component, an observer, who will monitor the servers entrusted to him, and on first request give us a hash state table for all servers. And some demon, constantly, violently pulls this component, monitoring the status of servers. Let it be the constructor of our observer:
var CasualObserver = function(){ var stack = []; this.add = function(server){ stack.push(server); return this; }; this.check = function(){ var hashTable = {}; for(var i = 0, ln = stack.length; i < ln; i++){ hashTable[stack[i].name] = stack[i].ping(); } return hashTable; } };
Suppose you are a programmer who commissioned this code, and, politely, asked him to optimize, while maintaining the existing interface.
')
Well, here you sit, and stare at these 14 lines, and the only (I ironically) thought that turns in your head - “is it worth to replace for while, or is it not worth it?”. This thought is both right and wrong (a kind of superposition of thought). The correct one is that the most time consuming operation here is a cycle. It’s wrong to think not about how to optimize it, but how to get rid of it. Why do we need to dynamically create a hash table, when we can work from an already finished one, and just call .check for each item?
this.check = function(){ return { stack[0].name : stack[0].ping(), stack[1].name : stack[1].ping(), stack[2].name : stack[2].ping() }; }
So we immediately get rid of the cycle. Of course, you look at me like a fool, and say - “Aha, Wan. But we can have an arbitrary number of servers, and not just three. And besides, there are no reflections in JS. ”
Did you know that primitive reflection is possible in Javascript? (you knew? Well then, go below) Yes, JS allows you to modify the existing code and create a new one right in runtime!
var sum = new Function('a', 'b', 'return alert(a + b);'); sum(2, 3);
With the same success, and for the same purposes, you can use all the hated eval. More about this already written in other posts on Habré.
Yeah, you probably already understand everything yourself? Of course! Let's create a constructor for our observer, who will create a check method for himself:
var SelfModifyObserver = function(){ var stack = []; this.add = function(server){ stack.push(server); var code = 'return {'; for(var i = 0, ln = stack.length; i < ln; i++){ code += stack[i].name + ':' + 'stack[' + i + '].ping(),'; } code += '};'; this.check = eval('(function(){' + code +'});'); return this; }; this.check = function(){return {};} };
It looks crazy, I totally agree with you. But it works!

Let's check whether this approach was justified or not. We will write a small function that will add to the observer 25 servers, one for each letter of the Latin alphabet, and then we will see how many times in a second he will be able to check for them.
var benchmark = function(instance, note){ for(var i=65; i<=90; i++){ instance.add(new Server(String.fromCharCode(i))); } var stamp = new Date().getTime(); var iterations = 0; while(new Date().getTime() - stamp <= 1000){ instance.check(); iterations++; } console.log(iterations + ' iterations per second for ' + note); return true; };
I have to admit that now I have no opportunity to test it in Node.js, but the tests in the office showed that on my server the performance gain for such a solution was about 30%.
And this is the result in chrome on my laptop:

You see! Squeezed 30% from almost empty space!
Thank you if you were interested.
The idea picked up in one of the reports at JSConf EU 2012.
Total: the post is not about how to write an observer to observe other objects, and how to get rid of the cycles. And how javascript can optimize your code on the go to achieve better performance.
A report from which I took this approach.Its text version.