Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 2eed4cf

Browse files
committed
perf(benchmark): add compile/link benchmarks
1 parent 6dfc188 commit 2eed4cf

File tree

3 files changed

+239
-0
lines changed

3 files changed

+239
-0
lines changed

benchmarks/compile-bp/app.js

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
var app = angular.module('compileBenchmark', []);
2+
3+
var registerDirective;
4+
app.config(function($compileProvider) {
5+
if ($compileProvider.debugInfoEnabled) {
6+
$compileProvider.debugInfoEnabled(false);
7+
}
8+
9+
registerDirective = function(name, config) {
10+
$compileProvider.directive(name, function() { return config; });
11+
};
12+
});
13+
14+
app.controller('DataController', function($element, $compile, $scope, $templateCache) {
15+
//The set of directives which have been created
16+
var directivesCreated = {};
17+
18+
//The current template being tested
19+
var template;
20+
21+
$scope.oJSON = JSON.stringify($scope.o = {});
22+
23+
$scope.$watch("oJSON", function(oJSON) {
24+
angular.copy(JSON.parse(oJSON), $scope.o);
25+
});
26+
27+
$scope.$watchCollection("o", function(options) {
28+
var json = $scope.oJSON = JSON.stringify(options);
29+
var directiveName = "test" + json.toLowerCase().replace(/[^a-z0-9]+/g, '');
30+
31+
if (!directivesCreated[directiveName]) {
32+
var directiveDef = {};
33+
34+
//Simple options
35+
directiveDef.replace = options.replace || false;
36+
directiveDef.transclude = options.transclude || false;
37+
directiveDef.multiElement = options.multiElement || false;
38+
directiveDef.controller = options.controller ? function testController(){} : undefined;
39+
40+
//Template
41+
if (options.templateType) {
42+
if (options.templateType === 'template') {
43+
directiveDef.template = '<div></div>';
44+
} else if (options.templateType === 'templateUrl') {
45+
$templateCache.put(directiveDef.templateUrl = directiveName + 'tmpl', '<div></div>');
46+
}
47+
}
48+
49+
//Link method(s)
50+
var link;
51+
if (options.preLink) {
52+
link = {pre: function testPreLink(){}, post: options.postLink && function testPostLink(){}};
53+
} else if (options.postLink) {
54+
link = function testLink(){};
55+
}
56+
57+
//Compile/link declaration
58+
if (options.compile) {
59+
directiveDef.compile = function testCompile() { return link; };
60+
} else if (link) {
61+
directiveDef.link = link;
62+
}
63+
64+
registerDirective(directiveName, directivesCreated[directiveName] = directiveDef);
65+
}
66+
67+
//Single vs multiElement spanning
68+
var eCount = options.elementCount || 1;
69+
if (eCount <= 1) {
70+
template = angular.element(document.createElement(directiveName));
71+
} else {
72+
template = angular.element();
73+
template[template.length++] = angular.element('<div>').attr(directiveName+'-start', '')[0];
74+
for (var i = 1; i < eCount - 1; i++) {
75+
template[template.length++] = document.createElement('span');
76+
}
77+
template[template.length++] = angular.element('<div>').attr(directiveName+'-end', '')[0];
78+
}
79+
80+
//Transcluded elements have children
81+
if (options.transclude) {
82+
template.append(document.createElement('div'));
83+
}
84+
85+
//Root element vs has-parent
86+
if (options.wrap) {
87+
template = angular.element(document.createElement('div')).append(template);
88+
}
89+
});
90+
91+
92+
93+
// TEST STEPS / STATE
94+
95+
var RUN_COUNT = 5000;
96+
97+
var linkFns = [];
98+
var elements = [];
99+
function pushElements(elms) {
100+
elements.push(elms);
101+
return elms;
102+
}
103+
104+
benchmarkSteps.push({
105+
name: 'compile',
106+
fn: function compile() {
107+
for (var i=0; i<RUN_COUNT; i++) {
108+
linkFns[i] = $compile( pushElements(template.clone()) );
109+
}
110+
}
111+
});
112+
113+
benchmarkSteps.push({
114+
name: 'link-clone',
115+
fn: function linkClone() {
116+
for (var i=0; i<RUN_COUNT; i++) {
117+
linkFns[i]($scope, pushElements);
118+
}
119+
}
120+
});
121+
122+
benchmarkSteps.push({
123+
name: 'link',
124+
fn: function link() {
125+
for (var i=0; i<RUN_COUNT; i++) {
126+
linkFns[i]($scope);
127+
}
128+
}
129+
});
130+
131+
benchmarkSteps.push({
132+
name: 'apply',
133+
fn: function linkApply() {
134+
$scope.$apply();
135+
}
136+
});
137+
138+
benchmarkSteps.push({
139+
name: 'destroy',
140+
fn: function destory() {
141+
while (elements.length) {
142+
elements.pop().remove();
143+
}
144+
linkFns = [];
145+
}
146+
});
147+
});

benchmarks/compile-bp/bp.conf.js

Lines changed: 11 additions & 0 deletions
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+
};

benchmarks/compile-bp/main.html

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<style>
2+
[ng-cloak] { display: none; }
3+
</style>
4+
<div ng-app="compileBenchmark" ng-cloak>
5+
<div ng-controller="DataController">
6+
<div class="container-fluid">
7+
<p>
8+
Directive $compile/link performance.
9+
</p>
10+
11+
<!-- A couple options aren't compatible or have requirements, just show a message -->
12+
<ul style="color:red">
13+
<li ng-if="o.multiElement && !o.wrap">Multi Element currently requires a parent node (Wrap)</li>
14+
<li ng-if="o.replace && !o.templateType">Replace without a template?</li>
15+
</ul>
16+
17+
<ul style="list-style:none">
18+
<li>
19+
<input type="text" ng-model="oJSON" width="250">
20+
</li>
21+
22+
<li>
23+
<label for="compile">Compile</label>
24+
<input type="checkbox" ng-model="o.compile" id="compile">
25+
</li>
26+
27+
<li>
28+
Link:
29+
<label for="preLink">PRE</label>
30+
<input type="checkbox" ng-model="o.preLink" id="preLink">
31+
<label for="postLink">POST</label>
32+
<input type="checkbox" ng-model="o.postLink" id="postLink">
33+
</li>
34+
35+
<li>
36+
Template:
37+
<label for="tt-none">None</label>
38+
<input type="radio" name="templateType" ng-model="o.templateType" ng-value="false" selected id="tt-none">
39+
<label for="tt-template">Yes</label>
40+
<input type="radio" name="templateType" ng-model="o.templateType" value="template" id="tt-template">
41+
<label for="tt-url">URL</label>
42+
<input type="radio" name="templateType" ng-model="o.templateType" value="templateUrl" id="tt-url">
43+
</li>
44+
45+
<li>
46+
<label for="replace">Replace</label>
47+
<input type="checkbox" ng-model="o.replace" id="replace">
48+
</li>
49+
50+
<li>
51+
Transclude:
52+
<label for="t-none">None</label>
53+
<input type="radio" ng-model="o.transclude" ng-value="false" id="t-none">
54+
<label for="t-yes">Yes</label>
55+
<input type="radio" ng-model="o.transclude" ng-value="true" id="t-yes">
56+
<label for="t-element">Element</label>
57+
<input type="radio" ng-model="o.transclude" value="element" id="t-element">
58+
</li>
59+
60+
<li>
61+
<label for="controller">Controller</label>
62+
<input type="checkbox" ng-model="o.controller" id="controller">
63+
</li>
64+
65+
<li>
66+
<label for="wrap">Wrap</label>
67+
<input type="checkbox" ng-model="o.wrap" id="wrap">
68+
</li>
69+
70+
<li>
71+
<label for="multiElement">Multi Element</label>
72+
<input type="checkbox" ng-model="o.multiElement" id="multiElement">
73+
<label for="elementCount" ng-show="o.multiElement">
74+
Elements
75+
<input type="number" ng-model="o.elementCount" id="elementCount" placeholder="1">
76+
</label>
77+
</li>
78+
</ul>
79+
</div>
80+
</div>
81+
</div>

0 commit comments

Comments
 (0)