Skip to content
This repository was archived by the owner on Sep 16, 2022. It is now read-only.

Commit 9eb1ef8

Browse files
committed
perf(ReflectiveProviders): Phase1, speed up resolveReflectiveProviders
Reduces resolveReflectiveProviders AWSM 22ms->12ms, CM 63ms->24ms for startup. ReflectiveInjection hashmap lookups reduced for runtime perf. useProperty: removed from provider api. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=153207714
1 parent e71c364 commit 9eb1ef8

13 files changed

+146
-114
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
### Breaking changes
66

7+
* Injecting null no longer supported.
8+
* Remove unused `useProperty` argument in DI `Provider` api.
9+
* `ReflectionCapabilities.isReflectionEnabled` renamed to `reflectionEnabled`.
10+
* Malformed CSS warnings are errors now.
11+
712
* Removed forms async validators. Alternative:
813

914
```dart

lib/src/compiler/compile_metadata.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ class CompileProviderMetadata {
153153
dynamic useValue;
154154
CompileTokenMetadata useExisting;
155155
CompileFactoryMetadata useFactory;
156-
String useProperty;
157156
List<CompileDiDependencyMetadata> deps;
158157
bool multi;
159158
CompileProviderMetadata(
@@ -162,7 +161,6 @@ class CompileProviderMetadata {
162161
this.useValue,
163162
this.useExisting,
164163
this.useFactory,
165-
this.useProperty,
166164
this.deps,
167165
bool multi})
168166
: this.multi = multi == true;
@@ -177,7 +175,6 @@ class CompileProviderMetadata {
177175
_objFromJson(data['useValue'], CompileIdentifierMetadata.fromJson),
178176
useFactory:
179177
_objFromJson(data['useFactory'], CompileFactoryMetadata.fromJson),
180-
useProperty: data['useProperty'],
181178
multi: data['multi'],
182179
deps: _arrayFromJson(data['deps'], CompileDiDependencyMetadata.fromJson)
183180
as List<CompileDiDependencyMetadata>);
@@ -192,7 +189,6 @@ class CompileProviderMetadata {
192189
'useExisting': _objToJson(useExisting),
193190
'useValue': _objToJson(useValue),
194191
'useFactory': _objToJson(useFactory),
195-
'useProperty': useProperty,
196192
'multi': multi,
197193
'deps': _arrayToJson(deps)
198194
};

lib/src/compiler/provider_parser.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ CompileProviderMetadata _transformProvider(CompileProviderMetadata provider,
338338
useExisting: useExisting,
339339
useFactory: provider.useFactory,
340340
useValue: useValue,
341-
useProperty: provider.useProperty,
342341
deps: deps,
343342
multi: provider.multi);
344343
}

lib/src/compiler/runtime_metadata.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ class RuntimeMetadataResolver {
249249
useExisting: provider.useExisting != null
250250
? this.getTokenMetadata(provider.useExisting)
251251
: null,
252-
useProperty: provider.useProperty,
253252
deps: compileDeps,
254253
multi: provider.multi);
255254
}

lib/src/compiler/view_compiler/compile_element.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,6 @@ class CompileElement extends CompileNode {
293293
} else {
294294
providerValue = convertValueToOutputAst(provider.useValue);
295295
}
296-
if (provider.useProperty != null) {
297-
providerValue = providerValue.prop(provider.useProperty);
298-
}
299296
providerValueExpressions.add(providerValue);
300297
}
301298
if (isLocalAlias) {

lib/src/core/di/provider.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ class Provider {
100100
/// Used in conjunction with dependencies.
101101
final Function useFactory;
102102

103-
/// Specifies the property of the configuration class to use as value.
104-
///
105-
/// Only used in conjunction with the @Injector class.
106-
final String useProperty;
107-
108103
/// Specifies a set of dependencies
109104
/// (as `token`s) which should be injected into the factory function.
110105
///
@@ -126,7 +121,6 @@ class Provider {
126121
this.useValue: noValueProvided,
127122
this.useExisting,
128123
this.useFactory,
129-
this.useProperty,
130124
List<Object> deps,
131125
bool multi})
132126
: dependencies = deps,

lib/src/core/di/reflective_injector.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ class ReflectiveInjectorImpl implements ReflectiveInjector {
750750
} catch (e, e_stack) {
751751
throw new InstantiationError(this, e, e_stack, provider.key);
752752
}
753-
return resolvedFactory.postProcess(obj);
753+
return obj;
754754
}
755755

756756
dynamic _getByReflectiveDependency(

lib/src/core/di/reflective_key.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ class KeyRegistry {
3232
var _allKeys = <Object, ReflectiveKey>{};
3333
ReflectiveKey get(Object token) {
3434
if (token is ReflectiveKey) return token;
35-
if (_allKeys.containsKey(token)) {
36-
return _allKeys[token];
37-
}
35+
var res = _allKeys[token];
36+
if (res != null) return res;
3837
var newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys);
3938
_allKeys[token] = newKey;
4039
return newKey;

lib/src/core/di/reflective_provider.dart

Lines changed: 112 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:angular2/src/facade/lang.dart' show assertionsEnabled;
44

55
import '../metadata.dart';
66
import 'decorators.dart';
7-
import 'provider.dart' show Provider, provide, noValueProvided;
7+
import 'provider.dart' show Provider, noValueProvided;
88
import 'reflective_exceptions.dart'
99
show
1010
NoAnnotationError,
@@ -15,22 +15,18 @@ import 'reflective_key.dart';
1515
/// [Dependency] is used by the framework to extend DI.
1616
/// This is internal to Angular and should not be used directly.
1717
class ReflectiveDependency {
18-
ReflectiveKey key;
19-
bool optional;
20-
dynamic lowerBoundVisibility;
21-
dynamic upperBoundVisibility;
22-
List<dynamic> properties;
18+
final ReflectiveKey key;
19+
final bool optional;
20+
final dynamic lowerBoundVisibility;
21+
final dynamic upperBoundVisibility;
22+
final List properties;
2323
ReflectiveDependency(this.key, this.optional, this.lowerBoundVisibility,
2424
this.upperBoundVisibility, this.properties);
2525
static ReflectiveDependency fromKey(ReflectiveKey key) {
26-
return new ReflectiveDependency(key, false, null, null, []);
26+
return new ReflectiveDependency(key, false, null, null, const []);
2727
}
2828
}
2929

30-
dynamic _identityPostProcess(obj) {
31-
return obj;
32-
}
33-
3430
/// An internal resolved representation of a [Provider] used by the [Injector].
3531
///
3632
/// It is usually created automatically by `Injector.resolveAndCreate`.
@@ -62,29 +58,26 @@ class ResolvedReflectiveProviderImpl implements ResolvedReflectiveBinding {
6258
ReflectiveKey key;
6359
List<ResolvedReflectiveFactory> resolvedFactories;
6460
bool multiProvider;
61+
6562
ResolvedReflectiveProviderImpl(
6663
this.key, this.resolvedFactories, this.multiProvider);
67-
ResolvedReflectiveFactory get resolvedFactory {
68-
return this.resolvedFactories[0];
69-
}
64+
65+
ResolvedReflectiveFactory get resolvedFactory => resolvedFactories.first;
7066
}
7167

7268
/// An internal resolved representation of a factory function created by
7369
/// resolving [Provider].
7470
class ResolvedReflectiveFactory {
75-
Function factory;
76-
List<ReflectiveDependency> dependencies;
77-
Function postProcess;
71+
final Function factory;
72+
final List<ReflectiveDependency> dependencies;
7873

7974
/// Constructs a resolved factory.
8075
///
8176
/// [factory] returns an instance of an object represented by a key.
8277
///
8378
/// [dependencies] is a list of dependencies passed to [factory] as
8479
/// parameters.
85-
///
86-
/// [postProcess] function is applied to the value constructed by [factory].
87-
ResolvedReflectiveFactory(this.factory, this.dependencies, this.postProcess);
80+
ResolvedReflectiveFactory(this.factory, this.dependencies);
8881
}
8982

9083
/// Resolve a single provider.
@@ -125,26 +118,27 @@ ResolvedReflectiveFactory resolveReflectiveFactory(Provider provider) {
125118
provider.dependencies,
126119
);
127120
}
128-
} else if (provider.useClass != null) {
129-
var useClass = provider.useClass;
130-
factoryFn = reflector.factory(useClass);
131-
resolvedDeps = _dependenciesFor(useClass);
132-
} else if (provider.useValue != noValueProvided) {
133-
factoryFn = () => provider.useValue;
134-
resolvedDeps = const <ReflectiveDependency>[];
135-
} else if (provider.token is Type) {
136-
var useClass = provider.token;
137-
factoryFn = reflector.factory(useClass);
138-
resolvedDeps = _dependenciesFor(useClass);
139121
} else {
140-
throw new InvalidProviderError.withCustomMessage(
141-
provider, 'token is not a Type and no factory was specified');
122+
var useClass = provider.useClass;
123+
if (useClass != null) {
124+
factoryFn = reflector.factory(useClass);
125+
resolvedDeps = _dependenciesFor(useClass);
126+
} else {
127+
var useValue = provider.useValue;
128+
if (useValue != noValueProvided) {
129+
factoryFn = () => useValue;
130+
resolvedDeps = const <ReflectiveDependency>[];
131+
} else if (provider.token is Type) {
132+
var useClass = provider.token;
133+
factoryFn = reflector.factory(useClass);
134+
resolvedDeps = _dependenciesFor(useClass);
135+
} else {
136+
throw new InvalidProviderError.withCustomMessage(
137+
provider, 'token is not a Type and no factory was specified');
138+
}
139+
}
142140
}
143-
144-
var postProcess = provider.useProperty != null
145-
? reflector.getter(provider.useProperty)
146-
: _identityPostProcess;
147-
return new ResolvedReflectiveFactory(factoryFn, resolvedDeps, postProcess);
141+
return new ResolvedReflectiveFactory(factoryFn, resolvedDeps);
148142
}
149143

150144
/// Converts the [Provider] into [ResolvedProvider].
@@ -160,33 +154,35 @@ ResolvedReflectiveProvider resolveReflectiveProvider(Provider provider) {
160154
List<ResolvedReflectiveProvider> resolveReflectiveProviders(
161155
List<dynamic /* Type | Provider | List < dynamic > */ > providers) {
162156
var normalized = _normalizeProviders(providers, []);
163-
var resolved = normalized.map(resolveReflectiveProvider).toList();
164-
return mergeResolvedReflectiveProviders(
165-
resolved, new Map<num, ResolvedReflectiveProvider>())
166-
.values
167-
.toList();
157+
var resolved = <ResolvedReflectiveProvider>[];
158+
for (int i = 0, len = normalized.length; i < len; i++) {
159+
resolved.add(resolveReflectiveProvider(normalized[i]));
160+
}
161+
return mergeResolvedReflectiveProviders(resolved);
168162
}
169163

170164
/// Merges a list of ResolvedProviders into a list where
171165
/// each key is contained exactly once and multi providers
172166
/// have been merged.
173-
Map<num, ResolvedReflectiveProvider> mergeResolvedReflectiveProviders(
174-
List<ResolvedReflectiveProvider> providers,
175-
Map<num, ResolvedReflectiveProvider> normalizedProvidersMap) {
176-
for (var i = 0; i < providers.length; i++) {
167+
List<ResolvedReflectiveProvider> mergeResolvedReflectiveProviders(
168+
List<ResolvedReflectiveProvider> providers) {
169+
// Map used to dedup by provider key id.
170+
var idToProvider = <num, ResolvedReflectiveProvider>{};
171+
for (var i = 0, len = providers.length; i < len; i++) {
177172
var provider = providers[i];
178-
var existing = normalizedProvidersMap[provider.key.id];
173+
var existing = idToProvider[provider.key.id];
179174
if (existing != null) {
180175
if (!identical(provider.multiProvider, existing.multiProvider)) {
181176
throw new MixingMultiProvidersWithRegularProvidersError(
182177
existing, provider);
183178
}
184179
if (provider.multiProvider) {
185-
for (var j = 0; j < provider.resolvedFactories.length; j++) {
180+
var factories = provider.resolvedFactories;
181+
for (var j = 0, len = factories.length; j < len; j++) {
186182
existing.resolvedFactories.add(provider.resolvedFactories[j]);
187183
}
188184
} else {
189-
normalizedProvidersMap[provider.key.id] = provider;
185+
idToProvider[provider.key.id] = provider;
190186
}
191187
} else {
192188
var resolvedProvider;
@@ -196,28 +192,31 @@ Map<num, ResolvedReflectiveProvider> mergeResolvedReflectiveProviders(
196192
} else {
197193
resolvedProvider = provider;
198194
}
199-
normalizedProvidersMap[provider.key.id] = resolvedProvider;
195+
idToProvider[provider.key.id] = resolvedProvider;
200196
}
201197
}
202-
return normalizedProvidersMap;
198+
return idToProvider.values.toList();
203199
}
204200

201+
// Flattens list of lists of providers into a flat list. If any entry is a
202+
// Type it converts it to a useClass provider.
205203
List<Provider> _normalizeProviders(
206204
List<dynamic /* Type | Provider | List < dynamic > */ > providers,
207205
List<Provider> res) {
208-
providers.forEach((b) {
206+
for (int i = 0, len = providers.length; i < len; i++) {
207+
var b = providers[i];
209208
if (b is Type) {
210-
res.add(provide(b, useClass: b));
211-
_normalizeProviders(const [], res);
209+
// If user listed a Type in provider list create Provide useClass: for it.
210+
// This is a shortcut to make provider lists easier to create.
211+
res.add(new Provider(b, useClass: b));
212212
} else if (b is Provider) {
213-
_normalizeProviders(const [], res);
214213
res.add(b);
215214
} else if (b is List) {
216215
_normalizeProviders(b, res);
217216
} else {
218217
throw new InvalidProviderError(b);
219218
}
220-
});
219+
}
221220
return res;
222221
}
223222

@@ -226,10 +225,12 @@ List<ReflectiveDependency> constructDependencies(
226225
if (dependencies == null) {
227226
return _dependenciesFor(typeOrFunc);
228227
} else {
229-
List<List<dynamic>> params = dependencies.map((t) => [t]).toList();
230-
return dependencies
231-
.map((t) => _extractToken(typeOrFunc, t, params))
232-
.toList();
228+
var deps = <ReflectiveDependency>[];
229+
for (int i = 0, len = dependencies.length; i < len; i++) {
230+
deps.add(_extractTokenUnwrappedParameters(
231+
typeOrFunc, dependencies[i], dependencies));
232+
}
233+
return deps;
233234
}
234235
}
235236

@@ -288,6 +289,56 @@ ReflectiveDependency _extractToken(
288289
token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
289290
}
290291

292+
// Same as _extractToken but doesn't expect list wrapped parameters. This is
293+
// to reduce GC by eliminating list allocations for each parameter.
294+
ReflectiveDependency _extractTokenUnwrappedParameters(
295+
typeOrFunc, metadata, List<dynamic> params) {
296+
var depProps = [];
297+
var token;
298+
var optional = false;
299+
if (metadata is! List) {
300+
if (metadata is Inject) {
301+
return _createDependency(metadata.token, optional, null, null, depProps);
302+
} else {
303+
return _createDependency(metadata, optional, null, null, depProps);
304+
}
305+
}
306+
var lowerBoundVisibility;
307+
var upperBoundVisibility;
308+
for (var i = 0; i < metadata.length; ++i) {
309+
var paramMetadata = metadata[i];
310+
if (paramMetadata is Type) {
311+
token = paramMetadata;
312+
} else if (paramMetadata is Inject) {
313+
token = paramMetadata.token;
314+
} else if (paramMetadata is Optional) {
315+
optional = true;
316+
} else if (paramMetadata is Self) {
317+
upperBoundVisibility = paramMetadata;
318+
} else if (paramMetadata is Host) {
319+
upperBoundVisibility = paramMetadata;
320+
} else if (paramMetadata is SkipSelf) {
321+
lowerBoundVisibility = paramMetadata;
322+
} else if (paramMetadata is DependencyMetadata) {
323+
if (paramMetadata.token != null) {
324+
token = paramMetadata.token;
325+
}
326+
depProps.add(paramMetadata);
327+
}
328+
}
329+
if (token == null) {
330+
// Since we have rare failure, wrap parameter types into a format that
331+
// NoAnnotationError expects in reflective mode.
332+
var paramList = <List<dynamic>>[];
333+
for (var param in params) {
334+
paramList.add([param]);
335+
}
336+
throw new NoAnnotationError(typeOrFunc, params);
337+
}
338+
return _createDependency(
339+
token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
340+
}
341+
291342
ReflectiveDependency _createDependency(
292343
token, optional, lowerBoundVisibility, upperBoundVisibility, depProps) {
293344
return new ReflectiveDependency(ReflectiveKey.get(token), optional,

0 commit comments

Comments
 (0)