Skip to content

Commit db72a4f

Browse files
committed
perf(view cache): Avoid http.get
This change makes templateUrl component creation 100% faster. It is a stop-gap until dart-archive#1107 is fixed. Closes dart-archive#1108
1 parent f32cac3 commit db72a4f

File tree

6 files changed

+35
-10
lines changed

6 files changed

+35
-10
lines changed

benchmark/web/tree-tmpl.html

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<span> {{ctrl.data.value}}
2+
<span ng-if="ctrl.data.right != null"><tree-url data=ctrl.data.right></span>
3+
<span ng-if="ctrl.data.left != null"><tree-url data=ctrl.data.left></span>
4+
</span>

benchmark/web/tree.dart

+10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ class TreeComponent {
1919
var data;
2020
}
2121

22+
@Component(
23+
selector: 'tree-url',
24+
templateUrl: 'tree-tmpl.html',
25+
publishAs: 'ctrl')
26+
class TreeUrlComponent {
27+
@NgOneWay('data')
28+
var data;
29+
}
30+
2231

2332
// This is a baseline implementation of TreeComponent.
2433
// It assumes the data never changes and simply throws elements on the DOM
@@ -239,6 +248,7 @@ main() {
239248

240249
var module = new Module()
241250
..type(TreeComponent)
251+
..type(TreeUrlComponent)
242252
..type(NgFreeTree)
243253
..type(NgFreeTreeScoped)
244254
..type(NgFreeTreeClass)

benchmark/web/tree.html

+2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
</p>
1515

1616
<div>Default: <input type=checkbox ng-model="useDefault"></div>
17+
<div>From URL: <input type=checkbox ng-model="useUrl"></div>
1718
<div>Baseline: <input type=checkbox ng-model="useBaseline"></div>
1819
<div>Baseline + scope: <input type=checkbox ng-model="useBaselineScoped"></div>
1920
<div>Baseline + class: <input type=checkbox ng-model="useBaselineClass"></div>
2021

2122

2223
<tree ng-if="useDefault" data=initData></tree>
24+
<tree-url ng-if="useUrl" data=initData></tree-url>
2325

2426
<ng-free-tree ng-if="useBaseline" data=initData></ng-free-tree>
2527
<ng-free-tree-scoped ng-if="useBaselineScoped" data=initData></ng-free-tree-scoped>

lib/core_dom/view_factory.dart

+10-2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class WalkingViewFactory implements ViewFactory {
118118
@Injectable()
119119
class ViewCache {
120120
// _viewFactoryCache is unbounded
121+
// This cache contains both HTML and URL keys.
121122
final viewFactoryCache = new LruCache<String, ViewFactory>();
122123
final Http http;
123124
final TemplateCache templateCache;
@@ -138,8 +139,15 @@ class ViewCache {
138139
}
139140

140141
async.Future<ViewFactory> fromUrl(String url, DirectiveMap directives) {
141-
return http.get(url, cache: templateCache).then(
142-
(resp) => fromHtml(resp.responseText, directives));
142+
ViewFactory viewFactory = viewFactoryCache.get(url);
143+
if (viewFactory == null) {
144+
return http.get(url, cache: templateCache).then((resp) {
145+
var viewFactoryFromHttp = fromHtml(resp.responseText, directives);
146+
viewFactoryCache.put(url, viewFactoryFromHttp);
147+
return viewFactoryFromHttp;
148+
});
149+
}
150+
return new async.Future.value(viewFactory);
143151
}
144152
}
145153

lib/core_dom/web_platform.dart

+9-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,14 @@ class PlatformViewCache implements ViewCache {
9191
}
9292

9393
async.Future<ViewFactory> fromUrl(String url, DirectiveMap directives) {
94-
return http.get(url, cache: templateCache).then(
95-
(resp) => fromHtml(resp.responseText, directives));
94+
ViewFactory viewFactory = viewFactoryCache.get(url);
95+
if (viewFactory == null) {
96+
return http.get(url, cache: templateCache).then((resp) {
97+
var viewFactoryFromHttp = fromHtml(resp.responseText, directives);
98+
viewFactoryCache.put(url, viewFactoryFromHttp);
99+
return viewFactoryFromHttp;
100+
});
101+
}
102+
return new async.Future.value(viewFactory);
96103
}
97104
}

test/core/templateurl_spec.dart

-6
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,9 @@ void main() {
269269
'<style>.hello{}</style><div log="SIMPLE">Simple!</div>'
270270
);
271271

272-
// Since the template cache is disabled, we expect a 'simple.html' call.
273-
backend
274-
..expectGET('simple.html').respond(200, '<div log="SIMPLE">Simple!</div>');
275-
276272
var element2 = e('<div><html-and-css>ignore</html-and-css><div>');
277273
compile([element2], directives)(injector, [element2]);
278274

279-
microLeap();
280-
backend.flush();
281275
microLeap();
282276

283277
expect(element2.children[0].shadowRoot).toHaveHtml(

0 commit comments

Comments
 (0)