Friday 27 March 2009

JavaScript / JScript Benchmark (en)

Beginning

I will not lie - I do not like to estimate a performance of javascript code. This procedure provides for the main project a lot of "unnecessary" and "senseless" code:
var n = 1000; 
var start = (new Date()).getTime();/
for (var i = 0 ; i < n; i++) {
    // bla-bla-bla ...
}
var stop = (new Date()).getTime();
var duration = stop - start;
var average = duration / n; 
document.writeln(average);
I can presume that all the familiar lines such as these. I may be interested in the performance of a function or method, and possibly, some of program. But I do not want to pollute my working project by some kind of garbage, such as this. Also I do not want this for function that I am trying to estimate - what algorithm is better.
When I finally tired of it - I decided to develop a Benchmark. The objective was to estimate the performance of not only function, but any piece of code, beginning from the line n and ending by line m.

Motivation

Starting this work, I understood - it is possible that this code has been realized already and successfully. Nevertheless I started ab ovo. When finishing I decided to compare my solution with solutions of my predecessors (links are in the bottom of the article). I will not overmodest - despite of some similarities, my solution is better. The argumentation is following - despite of similarity my code is universal essentially.
Then I will show - that is, and how it can be very convenient and simple tool. Partially similarities and differences of the actual solution and it’s predecessors will be consider.

Features of OO-approach in JavaScript

Any piece of code can be a body of nameless function (this is truth for JavaScript especially taking in account it’s special OO realization). E.g.:
var arr = [100, 200, 300, 400]; 
    var result = 0; 
    for (var i = 0; i < arr.length; i++) {
        result += arr[i];
    }
can be transformed to the next
var arr = [100, 200, 300, 400]; 
((function() 
{
    var result = 0; 
    for (var i = 0; i < arr.length; i++) {
        result += arr[i];
    }
})(); 

Realization

This means that for any function you can apply a method which can perform additional actions:
Function.prototype.eval = function()
This method is defined for internal object Function, it is a certain amount of times, while retaining the length function and prints some statistics about the performance.
Let's to examine an example of usage:
var arr = [1, 2, 3, 4];

function sum(arr)
{
   var result = 0;
   for (var i = 0; i < arr.length; i++) {
      result += arr[i];
   }
   return result;
}

// original code
var s = sum(arr);

// modified code
var s = sum.eval(arr);
When comparing the original and modified codes, it can be seen that a difference is minimal. The code is pure until now and the result allows analyzing of information.

Features

This solution does not use timers and can be performed in different environment such as the browser window and standalone applications. Also it consists of the additional code solving problem of platform independency.
What has been implemented additionally? In the difference of analogues this code works in the most of cases - JavaScript/JScript. To reach this feature some additional useful properties has been defined:
- Function.prototype.evalCount - integer parameter keeps the number of iterations, by default is1000.
- Function.prototype.evalDuration - integer parameter keeps duration of the code execution. It is evaluated during a benchmarking process and does not have default value.
- Function.prototype.evalPrint = function() - auxiliary function for output of statistics of the performance. It takes in account differences of environments and launches appropriate output method. By default, it outputs the number of iterations and duration.
Of course, these parameters can be redefined, e.g., change the number of iterations or change the method of the statistics output. And this can be performed both globally via the function’s prototype and locally for the actual function. E.g.:
sum.evalCount = 10240; // 10K iterations
var result = sum.eval(1, 2, 3, 4);

Benefits

In the contrast of analogues the suggested method:
1. allows a light embedding the performance code with minimal modifications of the main code;
2. has extended features of control;
3. independent of the environment and allows to use this extension without modification both JavaScript and JScript (Windows Scripting Host).

The full solution

The solution is environment independent. It has been tested for IE6, IE7, FF2.0.0.15, FF3.0.7 and Windows Scripting Host. It is distributed under the GPL. The source code is available by this link. Ibid - the download link.

References

1. John Resig's blog
2. webtoolkit site

No comments:

Post a Comment