Skip to content

Commit 200e829

Browse files
jbedardMichael Gallagher
authored and
Michael Gallagher
committed
test($parse): adding benchmark for execution of $parse()ed expressions
Part of angular#8901
1 parent 210bf04 commit 200e829

File tree

3 files changed

+290
-0
lines changed

3 files changed

+290
-0
lines changed
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
var app = angular.module('parsedExpressionBenchmark', []);
2+
3+
app.config(function($compileProvider) {
4+
if ($compileProvider.debugInfoEnabled) {
5+
$compileProvider.debugInfoEnabled(false);
6+
}
7+
});
8+
9+
app.filter('noop', function() {
10+
return function(input) {
11+
return input;
12+
};
13+
});
14+
15+
//Executes the specified expression as a watcher
16+
app.directive('bmPeWatch', function() {
17+
return {
18+
restrict: 'A',
19+
compile: function($element, $attrs) {
20+
$element.text( $attrs.bmPeWatch );
21+
return function($scope, $element, $attrs) {
22+
$scope.$watch($attrs.bmPeWatch, function(val) {
23+
$element.text(val);
24+
25+
});
26+
};
27+
}
28+
};
29+
});
30+
31+
//Executes the specified expression as a watcher
32+
//Adds a simple wrapper method to allow use of $watch instead of $watchCollection
33+
app.directive('bmPeWatchLiteral', function($parse) {
34+
function retZero() {
35+
return 0;
36+
}
37+
38+
return {
39+
restrict: 'A',
40+
compile: function($element, $attrs) {
41+
$element.text( $attrs.bmPeWatchLiteral );
42+
return function($scope, $element, $attrs) {
43+
$scope.$watch( $parse($attrs.bmPeWatchLiteral, retZero) );
44+
};
45+
}
46+
};
47+
});
48+
49+
app.controller('DataController', function($scope, $rootScope) {
50+
var totalRows = 10000;
51+
52+
var data = $scope.data = [];
53+
54+
var star = '*';
55+
56+
$scope.func = function() { return star;};
57+
58+
for (var i=0; i<totalRows; i++) {
59+
data.push({
60+
index: i,
61+
odd: i%2 === 0,
62+
even: i%2 === 1,
63+
str0: "foo-" + Math.random()*Date.now(),
64+
str1: "bar-" + Math.random()*Date.now(),
65+
str2: "baz-" + Math.random()*Date.now(),
66+
num0: Math.random()*Date.now(),
67+
num1: Math.random()*Date.now(),
68+
num2: Math.random()*Date.now(),
69+
date0: new Date(Math.random()*Date.now()),
70+
date1: new Date(Math.random()*Date.now()),
71+
date2: new Date(Math.random()*Date.now()),
72+
func: function(){ return star; },
73+
obj: data[i-1],
74+
keys: data[i-1] && (data[i-1].keys || Object.keys(data[i-1]))
75+
});
76+
}
77+
78+
benchmarkSteps.push({
79+
name: '$apply',
80+
fn: function() {
81+
for (var i=0; i<50; i++) {
82+
$rootScope.$digest();
83+
}
84+
}
85+
});
86+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = function(config) {
2+
config.set({
3+
scripts: [ {
4+
id: 'angular',
5+
src: '/build/angular.js'
6+
},
7+
{
8+
src: 'app.js',
9+
}]
10+
});
11+
};
+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<div ng-app="parsedExpressionBenchmark" ng-cloak>
2+
<div ng-controller="DataController">
3+
<div class="container-fluid">
4+
<p>
5+
Tests the execution of $parse()ed expressions. Each test tries to isolate specific expression types. Expressions should (probably) not be constant so they get evaluated per digest.
6+
</p>
7+
8+
<ul style="list-style:none">
9+
<li>
10+
<input type="radio" ng-model="expressionType" value="simplePath" id="simplePath">
11+
<label for="simplePath">Simple Paths</label>
12+
</li>
13+
14+
<li>
15+
<input type="radio" ng-model="expressionType" value="complexPath" id="complexPath">
16+
<label for="complexPath">Complex Paths</label>
17+
</li>
18+
19+
<li>
20+
<input type="radio" ng-model="expressionType" value="fieldAccess" id="fieldAccess">
21+
<label for="fieldAccess">Field Accessors</label>
22+
</li>
23+
24+
<li>
25+
<input type="radio" ng-model="expressionType" value="fieldIndex" id="fieldIndex">
26+
<label for="fieldIndex">Field Indexes</label>
27+
</li>
28+
29+
<li>
30+
<input type="radio" ng-model="expressionType" value="operators" id="operators">
31+
<label for="operators">Binary/Unary operators</label>
32+
</li>
33+
34+
<li>
35+
<input type="radio" ng-model="expressionType" value="filters" id="filters">
36+
<label for="filters">Filters</label>
37+
</li>
38+
39+
<li>
40+
<input type="radio" ng-model="expressionType" value="functionCalls" id="functionCalls">
41+
<label for="functionCalls">Function calls</label>
42+
</li>
43+
44+
<li>
45+
<input type="radio" ng-model="expressionType" value="objectLiterals" id="objectLiterals">
46+
<label for="objectLiterals">Object Literals</label>
47+
</li>
48+
49+
<li>
50+
<input type="radio" ng-model="expressionType" value="arrayLiterals" id="arrayLiterals">
51+
<label for="arrayLiterals">Array Literals</label>
52+
</li>
53+
</ul>
54+
55+
<!--
56+
NOTES:
57+
- ensure each tested expression has at least one variable in it to avoid constant expressions
58+
-->
59+
60+
<ul ng-switch="expressionType">
61+
<li ng-switch-when="simplePath" ng-repeat="(rowIdx, row) in ::data">
62+
<span bm-pe-watch="rowIdx"></span>
63+
<span bm-pe-watch="row.index"></span>
64+
<span bm-pe-watch="row.num0"></span>
65+
<span bm-pe-watch="row.num1"></span>
66+
<span bm-pe-watch="row.num2"></span>
67+
<span bm-pe-watch="row.str0"></span>
68+
<span bm-pe-watch="row.str1"></span>
69+
<span bm-pe-watch="row.str2"></span>
70+
<span bm-pe-watch="row.date0"></span>
71+
<span bm-pe-watch="row.obj"></span>
72+
<span bm-pe-watch="row.keys"></span>
73+
</li>
74+
75+
<li ng-switch-when="complexPath" ng-repeat="(rowIdx, row) in ::data">
76+
<span bm-pe-watch="row.index"></span>
77+
<span bm-pe-watch="row.num0"></span>
78+
<span bm-pe-watch="row.num1"></span>
79+
<span bm-pe-watch="row.str0"></span>
80+
<span bm-pe-watch="row.str1"></span>
81+
<span bm-pe-watch="row.obj.index"></span>
82+
<span bm-pe-watch="row.obj.index"></span>
83+
<span bm-pe-watch="row.obj.index"></span>
84+
<span bm-pe-watch="row.obj.obj.index"></span>
85+
<span bm-pe-watch="row.obj.obj.index"></span>
86+
<span bm-pe-watch="row.obj.obj.obj.index"></span>
87+
<span bm-pe-watch="row.obj.obj.obj.index"></span>
88+
</li>
89+
90+
<li ng-switch-when="fieldAccess" ng-repeat="(rowIdx, row) in ::data">
91+
<span bm-pe-watch="data[rowIdx].index"></span>
92+
<span bm-pe-watch="data[rowIdx].num0"></span>
93+
<span bm-pe-watch="data[rowIdx].num1"></span>
94+
<span bm-pe-watch="data[rowIdx].str0"></span>
95+
<span bm-pe-watch="data[rowIdx].str1"></span>
96+
<span bm-pe-watch="data[rowIdx].obj.index"></span>
97+
<span bm-pe-watch="data[rowIdx].obj.index"></span>
98+
<span bm-pe-watch="data[rowIdx].obj.index"></span>
99+
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
100+
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
101+
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
102+
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
103+
</li>
104+
105+
<li ng-switch-when="fieldIndex" ng-repeat="(rowIdx, row) in ::data">
106+
<span bm-pe-watch="data[rowIdx]"></span>
107+
<span bm-pe-watch="row['str0']"></span>
108+
<span bm-pe-watch="row['str1']"></span>
109+
<span bm-pe-watch="data[row['index']]['index']"></span>
110+
<span bm-pe-watch="data[rowIdx]['obj']"></span>
111+
<span bm-pe-watch="data[rowIdx]['obj']['obj']"></span>
112+
<span bm-pe-watch="row[row['keys'][0]]"></span>
113+
<span bm-pe-watch="row[row['keys'][1]]"></span>
114+
<span bm-pe-watch="row[row['keys'][2]]"></span>
115+
<span bm-pe-watch="row[row['keys'][3]]"></span>
116+
<span bm-pe-watch="row[row['keys'][4]]"></span>
117+
<span bm-pe-watch="row[row['keys'][5]]"></span>
118+
119+
</li>
120+
121+
<li ng-switch-when="operators" ng-repeat="(rowIdx, row) in ::data">
122+
<span bm-pe-watch="+rowIdx"></span>
123+
<span bm-pe-watch="-rowIdx"></span>
124+
<span bm-pe-watch="rowIdx + 1"></span>
125+
<span bm-pe-watch="rowIdx - 1"></span>
126+
<span bm-pe-watch="rowIdx * 2"></span>
127+
<span bm-pe-watch="rowIdx + -1"></span>
128+
<span bm-pe-watch="rowIdx - -1"></span>
129+
<span bm-pe-watch="-rowIdx * 2 + 1"></span>
130+
<span bm-pe-watch="rowIdx % 2"></span>
131+
<span bm-pe-watch="rowIdx % 2 === 1"></span>
132+
<span bm-pe-watch="rowIdx % 2 === 0"></span>
133+
<span bm-pe-watch="rowIdx / 1"></span>
134+
<span bm-pe-watch="-rowIdx * 2 * rowIdx + rowIdx / rowIdx + 1"></span>
135+
</li>
136+
137+
<li ng-switch-when="filters" ng-repeat="(rowIdx, row) in ::data">
138+
<span bm-pe-watch="rowIdx | noop"></span>
139+
<span bm-pe-watch="rowIdx | noop"></span>
140+
<span bm-pe-watch="rowIdx | noop"></span>
141+
<span bm-pe-watch="rowIdx | noop:1"></span>
142+
<span bm-pe-watch="rowIdx | noop:rowIdx"></span>
143+
<span bm-pe-watch="rowIdx | noop:1:2:3:4:5"></span>
144+
<span bm-pe-watch="rowIdx | noop:rowIdx:rowIdx:rowIdx"></span>
145+
<span bm-pe-watch="rowIdx | noop | noop"></span>
146+
<span bm-pe-watch="rowIdx | noop:1 | noop"></span>
147+
<span bm-pe-watch="rowIdx | noop | noop:null:undefined:0"></span>
148+
<span bm-pe-watch="rowIdx | noop | noop | noop"></span>
149+
<span bm-pe-watch="rowIdx | noop:1 | noop:2 | noop:3"></span>
150+
</li>
151+
152+
<li ng-switch-when="functionCalls" ng-repeat="(rowIdx, row) in ::data">
153+
<span bm-pe-watch="func()"></span>
154+
<span bm-pe-watch="func(1)"></span>
155+
<span bm-pe-watch="func(1, 2)"></span>
156+
<span bm-pe-watch="func(1, 2, 3)"></span>
157+
<span bm-pe-watch="row.func()"></span>
158+
<span bm-pe-watch="row.func(1)"></span>
159+
<span bm-pe-watch="row.func(1, 2)"></span>
160+
<span bm-pe-watch="row.func(1, 2, 3)"></span>
161+
<span bm-pe-watch="func(func())"></span>
162+
<span bm-pe-watch="func(func(), func())"></span>
163+
<span bm-pe-watch="row.func(row.func())"></span>
164+
<span bm-pe-watch="row.func(row.func(), row.func())"></span>
165+
</li>
166+
167+
<li ng-switch-when="objectLiterals" ng-repeat="(rowIdx, row) in ::data">
168+
<span bm-pe-watch-literal="{foo: rowIdx}"></span>
169+
<span bm-pe-watch-literal="{foo: row, bar: rowIdx}"></span>
170+
<span bm-pe-watch-literal="{0: row, 1: rowIdx, 2: 3}"></span>
171+
<span bm-pe-watch-literal="{str: 'foo', num: rowIdx, b: true}"></span>
172+
<span bm-pe-watch-literal="{a: {b: {c: {d: {e: {f: rowIdx}}}}}}"></span>
173+
<span bm-pe-watch-literal="{a: rowIdx, b: 1, c: 2, d: 3, e: 4, f: 5, g: rowIdx, h: 6, i: 7, j: 8, k: rowIdx}"></span>
174+
</li>
175+
176+
<li ng-switch-when="arrayLiterals" ng-repeat="(rowIdx, row) in ::data">
177+
<span bm-pe-watch-literal="[rowIdx]"></span>
178+
<span bm-pe-watch-literal="[rowIdx, 0]"></span>
179+
<span bm-pe-watch-literal="[rowIdx, 0, 1]"></span>
180+
<span bm-pe-watch-literal="[rowIdx, 0, 1, 2]"></span>
181+
<span bm-pe-watch-literal="[rowIdx, 0, 1, 2, 3]"></span>
182+
<span bm-pe-watch-literal="[[], [rowIdx], [], [], [3], [[[]]]]"></span>
183+
<span bm-pe-watch-literal="[rowIdx, undefined, null, true, false]"></span>
184+
<span bm-pe-watch-literal="[[][0], [0][0], [][rowIdx]]"></span>
185+
<span bm-pe-watch-literal="[0, rowIdx]"></span>
186+
<span bm-pe-watch-literal="[0, 1, rowIdx]"></span>
187+
<span bm-pe-watch-literal="[0, 1, 2, rowIdx]"></span>
188+
<span bm-pe-watch-literal="[0, 1, 2, 3, rowIdx]"></span>
189+
</li>
190+
</ul>
191+
</div>
192+
</div>
193+
</div>

0 commit comments

Comments
 (0)