From 1f4caa8773bf96de73b0ef7bd6526a93312cdcab Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 8 Oct 2014 16:15:38 -0400 Subject: [PATCH] feat(benchmark): add a simple benchmark for the di module --- .gitignore | 1 + gulpfile.js | 97 ++++++++++++++----- modules/benchmarks/src/di/benchmark.es5 | 15 +++ modules/benchmarks/src/di/bp.conf.es5 | 11 +++ .../src/di/injector_get_benchmark.js | 43 ++++++++ .../src/di/injector_get_by_key_benchmark.js | 46 +++++++++ .../src/di/injector_get_child_benchmark.js | 49 ++++++++++ .../src/di/injector_instantiate_benchmark.js | 45 +++++++++ modules/benchmarks/src/di/main.html | 0 modules/benchmarks/src/di/register_system.es5 | 10 ++ modules/di/src/key.js | 7 +- package.json | 2 + 12 files changed, 298 insertions(+), 28 deletions(-) create mode 100644 modules/benchmarks/src/di/benchmark.es5 create mode 100644 modules/benchmarks/src/di/bp.conf.es5 create mode 100644 modules/benchmarks/src/di/injector_get_benchmark.js create mode 100644 modules/benchmarks/src/di/injector_get_by_key_benchmark.js create mode 100644 modules/benchmarks/src/di/injector_get_child_benchmark.js create mode 100644 modules/benchmarks/src/di/injector_instantiate_benchmark.js create mode 100644 modules/benchmarks/src/di/main.html create mode 100644 modules/benchmarks/src/di/register_system.es5 diff --git a/.gitignore b/.gitignore index 0cafaa9020..b577071b1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Don’t commit the following directories created by pub. build/ +benchpress-build/ packages/ .buildlog node_modules diff --git a/gulpfile.js b/gulpfile.js index 34939bf8d7..399088f330 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -15,15 +15,24 @@ var fs = require('fs'); var path = require('path'); var readline = require('readline'); var Q = require('q'); +var merge = require('merge'); +var benchpress = require('angular-benchpress/lib/cli'); var js2es5Options = { annotations: true, // parse annotations types: true, // parse types script: false, // parse as a module - modules: 'register', + modules: 'instantiate' +}; + +var js2es5OptionsProd = merge(true, js2es5Options, { + typeAssertions: false +}); + +var js2es5OptionsDev = merge(true, js2es5Options, { typeAssertionModule: 'rtts_assert/rtts_assert', typeAssertions: true -}; +}); var js2dartOptions = { annotations: true, // parse annotations @@ -38,8 +47,11 @@ var gulpTraceur = require('./tools/transpiler/gulp-traceur'); // traceur runtime gulp.task('jsRuntime/build', function() { - var traceurRuntime = gulp.src(gulpTraceur.RUNTIME_PATH) - .pipe(gulp.dest('build/js')); + var traceurRuntime = gulp.src([ + gulpTraceur.RUNTIME_PATH, + "node_modules/es6-module-loader/dist/es6-module-loader-sans-promises.src.js", + "node_modules/systemjs/lib/extension-register.js" + ]).pipe(gulp.dest('build/js')); return traceurRuntime; }); @@ -47,7 +59,6 @@ gulp.task('jsRuntime/build', function() { // modules var sourceTypeConfigs = { dart: { - compilerOptions: js2dartOptions, transpileSrc: ['modules/**/*.js'], htmlSrc: ['modules/*/src/**/*.html'], copySrc: ['modules/**/*.dart'], @@ -56,7 +67,6 @@ var sourceTypeConfigs = { mimeType: 'application/dart' }, js: { - compilerOptions: js2es5Options, transpileSrc: ['modules/**/*.js', 'modules/**/*.es6'], htmlSrc: ['modules/*/src/**/*.html'], copySrc: ['modules/**/*.es5'], @@ -72,7 +82,7 @@ gulp.task('modules/clean', function() { }); gulp.task('modules/build.dart/src', function() { - return createModuleTask(sourceTypeConfigs.dart); + return createModuleTask(merge(sourceTypeConfigs.dart, {compilerOptions: js2dartOptions})); }); gulp.task('modules/build.dart/pubspec', function(done) { @@ -105,14 +115,24 @@ gulp.task('modules/build.dart/pubspec', function(done) { gulp.task('modules/build.dart', ['modules/build.dart/src', 'modules/build.dart/pubspec']); -gulp.task('modules/build.js', function() { - return createModuleTask(sourceTypeConfigs.js); +gulp.task('modules/build.dev.js', function() { + return createModuleTask(merge(true, sourceTypeConfigs.js, {compilerOptions: js2es5OptionsDev})); +}); + +gulp.task('modules/build.prod.js', function() { + return createModuleTask(merge(true, sourceTypeConfigs.js, {compilerOptions: js2es5OptionsProd})); }); function renameSrcToLib(file) { file.dirname = file.dirname.replace(/\bsrc\b/, 'lib'); } +function renameEs5ToJs(file) { + if (file.extname == '.es5') { + file.extname = '.js'; + } +} + function createModuleTask(sourceTypeConfig) { var transpile = gulp.src(sourceTypeConfig.transpileSrc) .pipe(rename({extname: '.'+sourceTypeConfig.outputExt})) @@ -121,6 +141,7 @@ function createModuleTask(sourceTypeConfig) { .pipe(gulp.dest(sourceTypeConfig.outputDir)); var copy = gulp.src(sourceTypeConfig.copySrc) .pipe(rename(renameSrcToLib)) + .pipe(rename(renameEs5ToJs)) .pipe(gulp.dest(sourceTypeConfig.outputDir)); // TODO: provide the list of files to the template // automatically! @@ -202,22 +223,50 @@ gulp.task('analyze/dartanalyzer', function(done) { }); + +// ------------------ +// BENCHMARKS + +var benchmarksBuildPath = 'build/benchpress'; +var benchmarksCompiledJsPath = 'build/js/benchmarks/lib'; + +gulp.task('benchmarks/build.benchpress', function () { + benchpress.build({ + benchmarksPath: benchmarksCompiledJsPath, + buildPath: benchmarksBuildPath + }) +}); + +gulp.task('benchmarks/build', function() { + runSequence( + ['jsRuntime/build', 'modules/build.prod.js'], + 'benchmarks/build.benchpress' + ); +}); + + + // ------------------ // WEB SERVER -gulp.task('serve', connect.server({ - root: [__dirname+'/build'], - port: 8000, - livereload: false, - open: false, - middleware: function() { - return [function(req, resp, next){ - if (req.url.match(/\.dart$/)) { - resp.setHeader("Content-Type", "application/dart"); - } - next(); - }]; - } -})); + +gulp.task('serve', function() { + connect.server({ + root: [__dirname+'/build'], + port: 8000, + livereload: false, + open: false, + middleware: function() { + return [function(req, resp, next){ + if (req.url.match(/\.dart$/)) { + resp.setHeader("Content-Type", "application/dart"); + } + next(); + }]; + } + })(); +}); + + // -------------- // general targets @@ -227,7 +276,7 @@ gulp.task('clean', ['modules/clean']); gulp.task('build', function(done) { runSequence( // parallel - ['jsRuntime/build', 'modules/build.dart', 'modules/build.js'], + ['jsRuntime/build', 'modules/build.dart', 'modules/build.dev.js'], // sequential 'analyze/dartanalyzer' ); diff --git a/modules/benchmarks/src/di/benchmark.es5 b/modules/benchmarks/src/di/benchmark.es5 new file mode 100644 index 0000000000..ed55f58711 --- /dev/null +++ b/modules/benchmarks/src/di/benchmark.es5 @@ -0,0 +1,15 @@ +System.import('benchmarks/di/injector_get_benchmark').then(function (bm) { + window.benchmarkSteps.push({name: 'Injector.get (token)', fn: bm.run}); +}, console.log.bind(console)); + +System.import('benchmarks/di/injector_get_by_key_benchmark').then(function (bm) { + window.benchmarkSteps.push({name: 'Injector.get (key)', fn: bm.run}); +}, console.log.bind(console)); + +System.import('benchmarks/di/injector_get_child_benchmark').then(function (bm) { + window.benchmarkSteps.push({name: 'Injector.get (grand x 5 child)', fn: bm.run}); +}, console.log.bind(console)); + +System.import('benchmarks/di/injector_instantiate_benchmark').then(function (bm) { + window.benchmarkSteps.push({name: 'Injector.instantiate', fn: bm.run}); +}, console.log.bind(console)); \ No newline at end of file diff --git a/modules/benchmarks/src/di/bp.conf.es5 b/modules/benchmarks/src/di/bp.conf.es5 new file mode 100644 index 0000000000..b9ff8a4015 --- /dev/null +++ b/modules/benchmarks/src/di/bp.conf.es5 @@ -0,0 +1,11 @@ +module.exports = function(config) { + config.set({ + scripts: [ + {src: '/js/traceur-runtime.js'}, + {src: '/js/es6-module-loader-sans-promises.src.js'}, + {src: '/js/extension-register.js'}, + {src: 'register_system.js'}, + {src: 'benchmark.js'} + ] + }); +}; diff --git a/modules/benchmarks/src/di/injector_get_benchmark.js b/modules/benchmarks/src/di/injector_get_benchmark.js new file mode 100644 index 0000000000..c3cc8c95fd --- /dev/null +++ b/modules/benchmarks/src/di/injector_get_benchmark.js @@ -0,0 +1,43 @@ +import {Injector} from "di/di"; + +var count = 0; + +export function run () { + var bindings = [A, B, C, D, E]; + var injector = new Injector(bindings); + + for (var i = 0; i < 20000; ++i) { + injector.get(D); + injector.get(E); + } +} + +class A { + constructor() { + count++; + } +} + +class B { + constructor(a:A) { + count++; + } +} + +class C { + constructor(b:B) { + count++; + } +} + +class D { + constructor(c:C, b:B) { + count++; + } +} + +class E { + constructor(d:D, c:C) { + count++; + } +} diff --git a/modules/benchmarks/src/di/injector_get_by_key_benchmark.js b/modules/benchmarks/src/di/injector_get_by_key_benchmark.js new file mode 100644 index 0000000000..6fd8669651 --- /dev/null +++ b/modules/benchmarks/src/di/injector_get_by_key_benchmark.js @@ -0,0 +1,46 @@ +import {Injector, Key} from "di/di"; + +var count = 0; + +export function run () { + var bindings = [A, B, C, D, E]; + var injector = new Injector(bindings); + + var D_KEY = Key.get(D); + var E_KEY = Key.get(E); + + for (var i = 0; i < 20000; ++i) { + injector.get(D_KEY); + injector.get(E_KEY); + } +} + +class A { + constructor() { + count++; + } +} + +class B { + constructor(a:A) { + count++; + } +} + +class C { + constructor(b:B) { + count++; + } +} + +class D { + constructor(c:C, b:B) { + count++; + } +} + +class E { + constructor(d:D, c:C) { + count++; + } +} diff --git a/modules/benchmarks/src/di/injector_get_child_benchmark.js b/modules/benchmarks/src/di/injector_get_child_benchmark.js new file mode 100644 index 0000000000..1aa1195695 --- /dev/null +++ b/modules/benchmarks/src/di/injector_get_child_benchmark.js @@ -0,0 +1,49 @@ +import {Injector, Key} from "di/di"; + +var count = 0; + +export function run () { + var bindings = [A, B, C, D, E]; + var injector = new Injector(bindings); + var childInjector = injector. + createChild([]). + createChild([]). + createChild([]). + createChild([]). + createChild([]); + + for (var i = 0; i < 20000; ++i) { + childInjector.get(D); + childInjector.get(E); + } +} + +class A { + constructor() { + count++; + } +} + +class B { + constructor(a:A) { + count++; + } +} + +class C { + constructor(b:B) { + count++; + } +} + +class D { + constructor(c:C, b:B) { + count++; + } +} + +class E { + constructor(d:D, c:C) { + count++; + } +} diff --git a/modules/benchmarks/src/di/injector_instantiate_benchmark.js b/modules/benchmarks/src/di/injector_instantiate_benchmark.js new file mode 100644 index 0000000000..b17b289c01 --- /dev/null +++ b/modules/benchmarks/src/di/injector_instantiate_benchmark.js @@ -0,0 +1,45 @@ +import {Injector, Key} from "di/di"; + +var count = 0; + +export function run () { + var bindings = [A, B, C, D]; + var injector = new Injector(bindings); + + for (var i = 0; i < 1000; ++i) { + var child = injector.createChild([E]); + child.get(E); + } + + console.log(count) +} + +class A { + constructor() { + count++; + } +} + +class B { + constructor(a:A) { + count++; + } +} + +class C { + constructor(b:B) { + count++; + } +} + +class D { + constructor(c:C, b:B) { + count++; + } +} + +class E { + constructor(d:D, c:C) { + count++; + } +} diff --git a/modules/benchmarks/src/di/main.html b/modules/benchmarks/src/di/main.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/benchmarks/src/di/register_system.es5 b/modules/benchmarks/src/di/register_system.es5 new file mode 100644 index 0000000000..388ec08a16 --- /dev/null +++ b/modules/benchmarks/src/di/register_system.es5 @@ -0,0 +1,10 @@ +System.paths = { + 'core/*': '/js/core/lib/*.js', + 'change_detection/*': '/js/change_detection/lib/*.js', + 'facade/*': '/js/facade/lib/*.js', + 'di/*': '/js/di/lib/*.js', + 'rtts_assert/*': '/js/rtts_assert/lib/*.js', + 'test_lib/*': '/js/test_lib/lib/*.js', + 'benchmarks/*': '/js/benchmarks/lib/*.js' +}; +register(System); diff --git a/modules/di/src/key.js b/modules/di/src/key.js index cbf324573b..b9ec259079 100644 --- a/modules/di/src/key.js +++ b/modules/di/src/key.js @@ -1,5 +1,5 @@ import {MapWrapper} from 'facade/collection'; -import {FIELD, int} from 'facade/lang'; +import {FIELD, int, isPresent} from 'facade/lang'; var _allKeys = {}; var _id:int = 0; @@ -15,9 +15,8 @@ export class Key { static get(token) { if (token instanceof Key) return token; - if (MapWrapper.contains(_allKeys, token)) { - return MapWrapper.get(_allKeys, token) - } + var obj = MapWrapper.get(_allKeys, token); + if (isPresent(obj)) return obj; var newKey = new Key(token, ++_id); MapWrapper.set(_allKeys, token, newKey); diff --git a/package.json b/package.json index 66826d5086..8f67a6ae71 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "es6-module-loader": "^0.9.2", "systemjs": "^0.9.1", + "angular-benchpress": "^0.1.3", "gulp": "^3.8.8", "gulp-rename": "^1.2.0", "gulp-watch": "^1.0.3", @@ -18,6 +19,7 @@ "karma-chrome-launcher": "^0.1.4", "karma-dart": "^0.2.8", "karma-jasmine": "^0.2.2", + "merge": "^1.2.0", "q": "^1.0.1", "through2": "^0.6.1", "event-stream": "^3.1.5",