javascriptbenchmark.js

Using string in benchmark.js


The example app for benchmark.js defines its performance tests as strings rather than JavaScript functions:

https://github.com/bestiejs/benchmark.js/blob/master/example/jsperf/index.html#L250

Is there an advantage to defining the performance test in this way? Why isn't it just a function?


Solution

  • From what I can tell, through a long series of calls the function code there ends up at a function in benchmark.js named getSource, which converts it to a string anyway:

    /**
     * Gets the source code of a function.
     *
     * @private
     * @param {Function} fn The function.
     * @param {String} altSource A string used when a function's source code is unretrievable.
     * @returns {String} The function's source code.
     */
    function getSource(fn, altSource) {
      var result = altSource;
      if (isStringable(fn)) {
        result = String(fn);
      } else if (support.decompilation) {
        // escape the `{` for Firefox 1
        result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
      }
      // trim string
      result = (result || '').replace(/^\s+|\s+$/g, '');
    
      // detect strings containing only the "use strict" directive
      return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
        ? ''
        : result;
    }
    

    This is done within the function "clock", which offers another explanation down the line as to its motiviations to making a benchmark function out of a string each time clock is called:

    // Compile in setup/teardown functions and the test loop.
    // Create a new compiled test, instead of using the cached `bench.compiled`,
    // to avoid potential engine optimizations enabled over the life of the test.
    

    I am no expert of benchmark.js, but my reading of it is that the library deliberately wants to start the benchmark from raw code, forcing the compiler/interpreter to run on code it's never seen before. This does make sense to me, as a hypothetical browser that freezes for five seconds on load to optimize the code might have amazing performance, but it would be unfair to ignore the five seconds it spent compiling in the benchmark. Also, it does a fair bit of modification to the original code in order to control the scope and exception handling; benchmark just needs the code as a string in order to properly manipulate it.

    In this view, it isn't so much that passing the functions as strings is particularly important, but there's no reason not to - it's going to end up as a string anyway.