diff --git a/bench/index.js b/bench/index.js new file mode 100644 index 0000000..08b3db3 --- /dev/null +++ b/bench/index.js @@ -0,0 +1,157 @@ +var fs = require('fs'); +var path = require('path') + +var Benchmark = require('benchmark'); + +var lube = require('..'); +var SOURCES_ROOT = path.join(__dirname, 'sources'); +var parsers = {}; +var sources = {}; + +try { + var esprima = require('esprima'); + parsers.esprima = function(src, withLoc) { + return esprima.parse(src, { loc: withLoc, ranges: withLoc }); + } +} catch (err) { + parsers.esprima = false; +} + +try { + var acorn = require('acorn'); + parsers.acorn = function(src, withLoc) { + return acorn.parse(src, { locations: withLoc }); + } +} +catch (err) { + parsers.acorn = false; +} + +parsers.lube = function(src, withLoc) { + return new lube.Parser(src).parseProgram(); +} + +console.log('Loading sources in memory..'); + +fs.readdirSync(SOURCES_ROOT).forEach(function (source) { + var file = path.join(SOURCES_ROOT, source); + + if (!fs.statSync(file).isFile()) throw new Error('Source ' + file + ' is not a file!'); + + sources[source] = fs.readFileSync(file, 'utf-8'); +}); + +console.log('Starting benchmarks..'); + + +function parseLater(parser, source) { + return function () { + return parsers[parser](sources[source], !false); + } +} + +var results = {}; + +Object.keys(parsers).forEach(function (parser) { + if (!parsers[parser]) { + console.log(' ' + parser + '... not found (skipped)'); + return; + } + + var suite = new Benchmark.Suite; + process.stdout.write(' ' + parser + '... '); + + Object.keys(sources).forEach(function (source) { + suite.add(source, parseLater(parser, source)); + }); + + suite.on('cycle', function (event) { + if (!results[parser]) results[parser] = {}; + + results[parser][event.target.name] = { // event.name === source name + speed: event.target.hz, // ops/sec + range: event.target.stats.rme, // +/- + times: event.target.stats.sample.length // how many runs + }; + }); + + suite.on('complete', function () { + console.log('done!'); + }) + + suite.run(); +}); + +// Now the results variable contains the result of our bench, and can be +// processed as you prefer. You could even use chalk for prettier output +// or/and pipe it to a file. + +/* Example output + ++----------------------------------------+ +| PARSER NAME | ++----------------------------------------+ +| filename | ops/sec | runs | ++----------+-----------------+-----------+ +| file 1 | 0000hz + 00% | 00 | +| file 2 | 0000hz + 00% | 00 | +| file 3 | 0000hz + 00% | 00 | ++----------+-----------------+-----------+ + +// */ + +var output = {}; + +var sourcesLenght = Object.keys(sources).reduce(function (pre, cur) { + return Math.max(pre, cur.length); +}, 'filename'.length); +var opsLength = '0000.00 +00.00%'.length; +var runsLength = 'runs'.length; +var totWidth = sourcesLenght + opsLength + runsLength + 6; +var banner = '+' + Array(totWidth + 3).join('-') + '+'; + +function pad(src, length, align, fill) { + length -= src.length; + if (length <= 0) return src; + + if (align === 'l') { + return src + Array(length + 1).join(fill); + } else if (align === 'r') { + return Array(length + 1).join(fill) + src; + } else { + return Array(~~(length / 2 + 0.5) + 1).join(fill) + src + Array(~~(length / 2) + 1).join(fill); + } +} + +Object.keys(parsers).forEach(function (parser) { + if (!parsers[parser]) return; + + console.log(banner); + console.log('| %s |', + pad(parser, totWidth, 'c', ' ') + ); + console.log(banner); + console.log( + '| %s | %s | %s |', + pad('filename', sourcesLenght, 'c', ' '), + pad('ops/sec', opsLength, 'c', ' '), + pad('runs', runsLength, 'c', ' ') + ); + console.log(banner); + + Object.keys(sources).forEach(function (source) { + var ops = pad(results[parser][source].speed.toFixed(2), 7, 'r', ' ') + + ' ' + pad('\xb1' + results[parser][source].range.toFixed(2) + '%', + 7, 'r', ' '); + console.log( + '| %s | %s | %s |', + pad(source, sourcesLenght, 'c', ' '), + ops, + pad(results[parser][source].times.toString(), runsLength, 'c', ' ') + ); + }); + + console.log(banner); +}); + +//console.log(results); diff --git a/sources/angular-1.2.5.js b/bench/sources/angular-1.2.5.js similarity index 100% rename from sources/angular-1.2.5.js rename to bench/sources/angular-1.2.5.js diff --git a/sources/backbone-1.1.0.js b/bench/sources/backbone-1.1.0.js similarity index 100% rename from sources/backbone-1.1.0.js rename to bench/sources/backbone-1.1.0.js diff --git a/sources/benchmark.js b/bench/sources/benchmark.js similarity index 100% rename from sources/benchmark.js rename to bench/sources/benchmark.js diff --git a/sources/jquery-1.9.1.js b/bench/sources/jquery-1.9.1.js similarity index 100% rename from sources/jquery-1.9.1.js rename to bench/sources/jquery-1.9.1.js diff --git a/sources/jquery.mobile-1.4.2.js b/bench/sources/jquery.mobile-1.4.2.js similarity index 100% rename from sources/jquery.mobile-1.4.2.js rename to bench/sources/jquery.mobile-1.4.2.js diff --git a/sources/mootools-1.4.5.js b/bench/sources/mootools-1.4.5.js similarity index 100% rename from sources/mootools-1.4.5.js rename to bench/sources/mootools-1.4.5.js diff --git a/sources/underscore-1.5.2.js b/bench/sources/underscore-1.5.2.js similarity index 100% rename from sources/underscore-1.5.2.js rename to bench/sources/underscore-1.5.2.js diff --git a/sources/yui-3.12.0.js b/bench/sources/yui-3.12.0.js similarity index 100% rename from sources/yui-3.12.0.js rename to bench/sources/yui-3.12.0.js diff --git a/package.json b/package.json index 888e14e..b43329c 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "url": "https://github.com/icefapper/jsRube/issues" }, "license": "MIT", - "dependencies": [ "benchmark" ], "keywords": [ "ast", "ecmascript", @@ -43,9 +42,14 @@ ], "scripts": { "test": "node run-tests.js", - "benchmark": "node speed.js" + "benchmark": "node bench" }, "devDependencies": { - "benchmark": "^2.1.0" + "benchmark": "^2.1.0", + "microtime": "^2.1.1" + }, + "optionalDependencies": { + "acorn": "^3.2.0", + "esprima": "^2.7.2" } } diff --git a/speed.js b/speed.js deleted file mode 100644 index 3023d15..0000000 --- a/speed.js +++ /dev/null @@ -1,80 +0,0 @@ -var parsers = {}; - -try { - var pEsprima = require( 'esprima' ); - parsers.esprima = function(src, withLoc) { - return pEsprima.parse(src, { loc: withLoc, ranges: withLoc }); - }; -} catch ( e ) {} - -try { - var pAcorn = require( 'acorn' ); - parsers.acorn = function( src, withLoc ) { - return pAcorn.parse(src, { locations: withLoc }); - }; -} catch ( e ) {} - -try { - var pLube = require( './lube.js' ); - parsers.lube = function( src, withLoc ) { - return new pLube.Parser(src).parseProgram(); - } -} catch ( e ) {} - -var fs = require( 'fs' ); -function readFile(filePath) { - try { - return fs.readFileSync(filePath,'utf-8').toString(); - } catch ( e ) { - console.log( "COULD NOT LOAD", filePath ); - return ""; - } -} - -var SOURCES_ROOT = './sources'; -var sources = {}; - -var files = fs .readdirSync ( SOURCES_ROOT ); - -var e = 0; - -while ( e < files.length ) { - if ( !fs.statSync (SOURCES_ROOT + '/' + files[e]).isDirectory() ) { - sources[files[e]] = readFile(SOURCES_ROOT+ '/' + files[e]); - console.log( 'LOAD', files[e] ); - } - - e++ ; -} - -sources['lube'] = readFile( './lube.js' ); - -var Benchmark = require( 'benchmark' ).Benchmark ; -var parserName, sourceName; - -function parseLater( parserName, sourceName ) { - return function() { return parsers[parserName](sources[sourceName], !false ); }; - -} - -for ( sourceName in sources ) { - var benchmarkSet = new Benchmark.Suite(); - for ( parserName in parsers ) { - benchmarkSet.add( parserName, parseLater(parserName, sourceName) ); - } - benchmarkSet.on( 'complete', function(r) { - var currentTargets = r.currentTarget, i; - i = 0; - console.log( "-----------START---------\n", - "source: ", sourceName ); - while ( i < currentTargets.length ) { - console.log( currentTargets[i].stats.mean, "(" + currentTargets[i].name + ')' ) - i++; - } - console.log( "------------DONE---------\n\n"); - }); - - benchmarkSet.run(); -} - -