diff --git a/modules/benchmarks/src/benchpress.dart b/modules/benchmarks/src/benchpress.dart new file mode 100644 index 0000000000..81542709bd --- /dev/null +++ b/modules/benchmarks/src/benchpress.dart @@ -0,0 +1,63 @@ +library benchmarks.benchpress; + +import 'dart:js' as js; +import 'dart:html'; +import 'dart:async'; + +// TODO: move the functionality of this module into benchpress and replace this +// file with a Dart wrapper! + +var _benchmarkNames = []; + +_benchmarkId(index) { + return "benchmark${index}"; +} + +_useBenchmark(index) { + var search = window.location.search; + if (search.length > 0) { + search = search.substring(1); + } + if (search.length > 0) { + return search == _benchmarkId(index); + } else { + return true; + } +} + +_onLoad(callback) { + var isReady = document.readyState == 'complete'; + if (isReady) { + Timer.run(callback); + } else { + window.addEventListener('load', (event) => callback(), false); + } +} + +_createBenchmarkMenu() { + var div = document.createElement('div'); + div.innerHtml += '

Benchmarks:

All'; + for (var i=0; i<_benchmarkNames.length; i++) { + var activeClass = _useBenchmark(i) ? 'active' : ''; + div.innerHtml += '${_benchmarkNames[i]}'; + } + document.body.insertBefore(div, document.body.childNodes[0]); +} + +benchmark(name, stepsCreationCallback) { + _benchmarkNames.add(name); + if (_benchmarkNames.length == 2) { + _onLoad(_createBenchmarkMenu); + } + if (_useBenchmark(_benchmarkNames.length-1)) { + stepsCreationCallback(); + } +} + +benchmarkStep(name, callback) { + var benchmarkName = _benchmarkNames[_benchmarkNames.length-1]; + js.context['benchmarkSteps'].add(new js.JsObject.jsify({ + "name": benchmarkName + '#' + name, + "fn": new js.JsFunction.withThis((_) => callback()) + })); +} diff --git a/modules/benchmarks/src/benchpress.es6 b/modules/benchmarks/src/benchpress.es6 new file mode 100644 index 0000000000..d5e5d5e0df --- /dev/null +++ b/modules/benchmarks/src/benchpress.es6 @@ -0,0 +1,55 @@ +// TODO: move the functionality of this module into benchpress itself! + +var benchmarkNames = []; + +function benchmarkId(index) { + return 'benchmark' + index; +} + +function useBenchmark(index) { + var search = window.location.search; + if (search.length > 0) { + search = search.substring(1); + } + if (search.length > 0) { + return search == benchmarkId(index); + } else { + return true; + } +} + +function onLoad(callback) { + var isReady = document.readyState === 'complete'; + if (isReady) { + window.setTimeout(callback); + } else { + window.addEventListener('load', callback, false); + } +} + +function createBenchmarkMenu() { + var div = document.createElement('div'); + div.innerHTML += '

Benchmarks:

All'; + for (var i=0; i'+benchmarkNames[i]+''); + } + document.body.insertBefore(div, document.body.childNodes[0]); +} + +export function benchmark(name, stepsCreationCallback) { + benchmarkNames.push(name); + if (benchmarkNames.length === 2) { + onLoad(createBenchmarkMenu); + } + if (useBenchmark(benchmarkNames.length-1)) { + stepsCreationCallback(); + } +} + +export function benchmarkStep(name, callback) { + var benchmarkName = benchmarkNames[benchmarkNames.length-1]; + window.benchmarkSteps.push({ + name: benchmarkName + '#' + name, fn: callback + }); +} diff --git a/modules/benchmarks/src/compiler/benchmark.dart b/modules/benchmarks/src/compiler/benchmark.dart index d78e810612..c8aa1fc047 100644 --- a/modules/benchmarks/src/compiler/benchmark.dart +++ b/modules/benchmarks/src/compiler/benchmark.dart @@ -2,35 +2,8 @@ library compiler_benchmark; import './selector_benchmark.dart' as sbm; import './compiler_benchmark.dart' as cbm; -import 'dart:js' as js; main () { - sbm.setup(); - cbm.setup(); - - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "CssSelector.parse * 1000", - "fn": new js.JsFunction.withThis((_) => sbm.runParse()) - })); - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "SelectorMatcher.addSelectable * 1000", - "fn": new js.JsFunction.withThis((_) => sbm.runAdd()) - })); - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "SelectorMatcher.match * 1000", - "fn": new js.JsFunction.withThis((_) => sbm.runMatch()) - })); - - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "Compiler.compile empty template", - "fn": new js.JsFunction.withThis((_) => cbm.compileEmptyTemplate()) - })); - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "Compiler.compile 25 element no bindings", - "fn": new js.JsFunction.withThis((_) => cbm.compile25ElementsNoBindings()) - })); - js.context['benchmarkSteps'].add(new js.JsObject.jsify({ - "name": "Compiler.compile 25 element with bindings", - "fn": new js.JsFunction.withThis((_) => cbm.compile25ElementsWithBindings()) - })); + sbm.main(); + cbm.main(); } \ No newline at end of file diff --git a/modules/benchmarks/src/compiler/benchmark.es5 b/modules/benchmarks/src/compiler/benchmark.es5 index 4be167af17..760118bd84 100644 --- a/modules/benchmarks/src/compiler/benchmark.es5 +++ b/modules/benchmarks/src/compiler/benchmark.es5 @@ -1,35 +1,9 @@ -System.import('benchmarks/compiler/selector_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'CssSelector.parse * 1000', fn: bm.runParse}); -}, console.log.bind(console)); - -System.import('benchmarks/compiler/selector_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'SelectorMatcher.addSelectable * 1000', fn: bm.runAdd}); -}, console.log.bind(console)); - -System.import('benchmarks/compiler/selector_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'SelectorMatcher.match * 1000', fn: bm.runMatch}); -}, console.log.bind(console)); - -System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'Compiler.compile empty template', fn: bm.compileEmptyTemplate}); -}, console.log.bind(console)); - -System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'Compiler.compile 25 element no bindings', fn: bm.compile25ElementsNoBindings}); -}, console.log.bind(console)); - -System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) { - bm.setup(); - - window.benchmarkSteps.push({name: 'Compiler.compile 25 element with bindings', fn: bm.compile25ElementsWithBindings}); +Promise.all([ + System.import('benchmarks/compiler/selector_benchmark'), + System.import('benchmarks/compiler/compiler_benchmark'), + System.import('benchmarks/compiler/compiler_benchmark_ng13') +]).then(function (benchmarks) { + benchmarks.forEach(function(bm) { + bm.main(); + }); }, console.log.bind(console)); diff --git a/modules/benchmarks/src/compiler/bp.conf.es5 b/modules/benchmarks/src/compiler/bp.conf.es5 index b9ff8a4015..7991da976d 100644 --- a/modules/benchmarks/src/compiler/bp.conf.es5 +++ b/modules/benchmarks/src/compiler/bp.conf.es5 @@ -4,7 +4,8 @@ module.exports = function(config) { {src: '/js/traceur-runtime.js'}, {src: '/js/es6-module-loader-sans-promises.src.js'}, {src: '/js/extension-register.js'}, - {src: 'register_system.js'}, + {src: 'paths.js'}, + {src: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js'}, {src: 'benchmark.js'} ] }); diff --git a/modules/benchmarks/src/compiler/compiler_benchmark.js b/modules/benchmarks/src/compiler/compiler_benchmark.js index 5b9ed81864..5f6a82e2bb 100644 --- a/modules/benchmarks/src/compiler/compiler_benchmark.js +++ b/modules/benchmarks/src/compiler/compiler_benchmark.js @@ -1,4 +1,9 @@ -import {DOM} from 'facade/dom'; +import {benchmark, benchmarkStep} from '../benchpress'; + +import {DOM, document} from 'facade/dom'; +import {isBlank} from 'facade/lang'; +import {MapWrapper} from 'facade/collection'; +import {AnnotatedType} from 'core/compiler/annotated_type'; import {Parser} from 'change_detection/parser/parser'; import {ClosureMap} from 'change_detection/parser/closure_map'; @@ -11,39 +16,65 @@ import {Component} from 'core/annotations/component'; import {Decorator} from 'core/annotations/decorator'; import {TemplateConfig} from 'core/annotations/template_config'; +var COUNT = 30; + var compiler; var annotatedComponent; -var annotatedComponentNoDirectives; -var emptyTemplate; -var templateWith25ElementsNoBindings; -var templateWith25ElementsAndBindings; - -export function setup() { +function setup() { var closureMap = new ClosureMap(); - var reflector = new Reflector(); + var reflector = new CachingReflector(); compiler = new Compiler(null, reflector, new Parser(new Lexer(), closureMap), closureMap); - annotatedComponent = reflector.annotatedType(SomeComponent); - annotatedComponentNoDirectives = reflector.annotatedType(ComponentWithNoDirectives); - - emptyTemplate = createTemplate('
'); - templateWith25ElementsNoBindings = buildTemplateWith25ElementsNoBindings(); - templateWith25ElementsAndBindings = buildTemplateWith25ElementsAndBindings(); + annotatedComponent = reflector.annotatedType(BenchmarkComponent); } -export function compileEmptyTemplate() { - var template = emptyTemplate; - return compiler.compileWithCache(null, annotatedComponent, template); +export function main() { + setup(); + + benchmark(`Compiler.compile 5*${COUNT} element no bindings`, function() { + var template = loadTemplate('templateNoBindings', COUNT); + + benchmarkStep('run', function() { + // Need to clone every time as the compiler might modify the template! + var cloned = DOM.clone(template); + compiler.compileWithCache(null, annotatedComponent, cloned); + }); + }); + + benchmark(`Compiler.compile 5*${COUNT} element with bindings`, function() { + var template = loadTemplate('templateWithBindings', COUNT); + + benchmarkStep('run', function() { + // Need to clone every time as the compiler might modify the template! + var cloned = DOM.clone(template); + compiler.compileWithCache(null, annotatedComponent, cloned); + }); + }); } -export function compile25ElementsWithBindings() { - var template = templateWith25ElementsAndBindings; - return compiler.compileWithCache(null, annotatedComponent, template); +function loadTemplate(templateId, repeatCount) { + var template = DOM.querySelectorAll(document, `#${templateId}`)[0]; + var content = DOM.getInnerHTML(template); + var result = ''; + for (var i=0; i -// -function buildTemplateWith25ElementsNoBindings() { - var result = ''; - for (var i=0; i<5; i++) { - for (var j=0; j<5; j++) { - result += '
-// {{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}} -//
-function buildTemplateWith25ElementsAndBindings() { - var result = ''; - for (var i=0; i<5; i++) { - for (var j=0; j<5; j++) { - result += '
elements... + var div = document.createElement('div'); + div.innerHTML = result; + return div; +} + +angular.module('app', []) +.directive('dir0', function($parse) { + return { + compile: function($element, $attrs) { + var expr = $parse($attrs.attr0); + return function($scope) { + $scope.$watch(expr, angular.noop); + } + } + }; +}) +.directive('dir1', function($parse) { + return { + compile: function($element, $attrs) { + var expr = $parse($attrs.attr1); + return function($scope) { + $scope.$watch(expr, angular.noop); + } + } + }; +}) +.directive('dir2', function($parse) { + return { + compile: function($element, $attrs) { + var expr = $parse($attrs.attr2); + return function($scope) { + $scope.$watch(expr, angular.noop); + } + } + }; +}) +.directive('dir3', function($parse) { + return { + compile: function($element, $attrs) { + var expr = $parse($attrs.attr3); + return function($scope) { + $scope.$watch(expr, angular.noop); + } + } + }; +}) +.directive('dir4', function($parse) { + return { + compile: function($element, $attrs) { + var expr = $parse($attrs.attr4); + return function($scope) { + $scope.$watch(expr, angular.noop); + } + } + }; +}) +.run(function(_$compile_) { + $compile = _$compile_; +}); + diff --git a/modules/benchmarks/src/compiler/main.html b/modules/benchmarks/src/compiler/main.html index e69de29bb2..d16b04e8fa 100644 --- a/modules/benchmarks/src/compiler/main.html +++ b/modules/benchmarks/src/compiler/main.html @@ -0,0 +1,30 @@ + + + diff --git a/modules/benchmarks/src/compiler/register_system.es5 b/modules/benchmarks/src/compiler/paths.es5 similarity index 100% rename from modules/benchmarks/src/compiler/register_system.es5 rename to modules/benchmarks/src/compiler/paths.es5 diff --git a/modules/benchmarks/src/compiler/selector_benchmark.js b/modules/benchmarks/src/compiler/selector_benchmark.js index 34d558ee07..7873c43686 100644 --- a/modules/benchmarks/src/compiler/selector_benchmark.js +++ b/modules/benchmarks/src/compiler/selector_benchmark.js @@ -1,3 +1,5 @@ +import {benchmark, benchmarkStep} from '../benchpress'; + import {SelectorMatcher} from "core/compiler/selector"; import {CssSelector} from "core/compiler/selector"; import {StringWrapper, Math} from 'facade/lang'; @@ -9,46 +11,55 @@ var fixedSelectors = []; var COUNT = 1000; -export function setup() { - for (var i=0; i { + matchCount += selected; + }); + } + return matchCount; + }); + }); +} + +function setup(count) { + for (var i=0; i { - count += selected; - }); - } - return count; -} - function randomSelector() { var res = randomStr(5); for (var i=0; i<3; i++) { diff --git a/modules/change_detection/src/parser/closure_map.dart b/modules/change_detection/src/parser/closure_map.dart index 615ee34b27..5f4ae78d19 100644 --- a/modules/change_detection/src/parser/closure_map.dart +++ b/modules/change_detection/src/parser/closure_map.dart @@ -1,3 +1,5 @@ +library change_detection.parser.closure_map; + import 'dart:mirrors'; typedef SetterFn(Object obj, value); diff --git a/modules/facade/src/dom.dart b/modules/facade/src/dom.dart index 4a08921ec8..4685340521 100644 --- a/modules/facade/src/dom.dart +++ b/modules/facade/src/dom.dart @@ -3,7 +3,7 @@ library angular.core.facade.dom; import 'dart:html'; import 'dart:js' show JsObject; -export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text; +export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text, document, location; // TODO(tbosch): Is there a builtin one? Why is Dart // removing unknown elements by default? diff --git a/modules/facade/src/dom.es6 b/modules/facade/src/dom.es6 index c5c722f983..e3be55146c 100644 --- a/modules/facade/src/dom.es6 +++ b/modules/facade/src/dom.es6 @@ -4,6 +4,9 @@ export var NodeList = window.NodeList; export var Text = window.Text; export var Element = window.HTMLElement; export var TemplateElement = window.HTMLTemplateElement; +export var document = window.document; +export var location = window.location; + import {List, MapWrapper} from 'facade/collection'; export class DOM {