Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 3de00bd

Browse files
mheverychirayuk
authored andcommitted
perf(watch-group): remove expression coalescing
Coalescing is rare but slows down WatchGroup creation. Closes #1328
1 parent 543863b commit 3de00bd

File tree

2 files changed

+14
-36
lines changed

2 files changed

+14
-36
lines changed

lib/change_detection/watch_group.dart

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
5454
final ChangeDetectorGroup<_Handler> _changeDetector;
5555
/** A cache for sharing sub expression watching. Watching `a` and `a.b` will
5656
* watch `a` only once. */
57-
final Map<String, WatchRecord<_Handler>> _cache;
5857
final RootWatchGroup _rootGroup;
5958

6059
/// STATS: Number of field watchers which are in use.
@@ -108,7 +107,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
108107
WatchGroup _prevWatchGroup, _nextWatchGroup;
109108

110109
WatchGroup._child(_parentWatchGroup, this._changeDetector, this.context,
111-
this._cache, this._rootGroup)
110+
this._rootGroup)
112111
: _parentWatchGroup = _parentWatchGroup,
113112
id = '${_parentWatchGroup.id}.${_parentWatchGroup._nextChildId++}'
114113
{
@@ -119,8 +118,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
119118
WatchGroup._root(this._changeDetector, this.context)
120119
: id = '',
121120
_rootGroup = null,
122-
_parentWatchGroup = null,
123-
_cache = new HashMap<String, WatchRecord<_Handler>>()
121+
_parentWatchGroup = null
124122
{
125123
_marker.watchGrp = this;
126124
_evalWatchTail = _evalWatchHead = _marker;
@@ -139,10 +137,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
139137
}
140138

141139
Watch watch(AST expression, ReactionFn reactionFn) {
142-
WatchRecord<_Handler> watchRecord = _cache[expression.expression];
143-
if (watchRecord == null) {
144-
_cache[expression.expression] = watchRecord = expression.setupWatch(this);
145-
}
140+
WatchRecord<_Handler> watchRecord = expression.setupWatch(this);
146141
return watchRecord.handler.addReactionFn(reactionFn);
147142
}
148143

@@ -161,10 +156,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
161156
_fieldCost++;
162157
fieldHandler.watchRecord = watchRecord;
163158

164-
WatchRecord<_Handler> lhsWR = _cache[lhs.expression];
165-
if (lhsWR == null) {
166-
lhsWR = _cache[lhs.expression] = lhs.setupWatch(this);
167-
}
159+
WatchRecord<_Handler> lhsWR = lhs.setupWatch(this);
168160

169161
// We set a field forwarding handler on LHS. This will allow the change
170162
// objects to propagate to the current WatchRecord.
@@ -180,10 +172,7 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
180172
var watchRecord = _changeDetector.watch(null, null, collectionHandler);
181173
_collectionCost++;
182174
collectionHandler.watchRecord = watchRecord;
183-
WatchRecord<_Handler> astWR = _cache[ast.expression];
184-
if (astWR == null) {
185-
astWR = _cache[ast.expression] = ast.setupWatch(this);
186-
}
175+
WatchRecord<_Handler> astWR = ast.setupWatch(this);
187176

188177
// We set a field forwarding handler on LHS. This will allow the change
189178
// objects to propagate to the current WatchRecord.
@@ -234,32 +223,23 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
234223
invokeHandler.watchRecord = evalWatchRecord;
235224

236225
if (lhsAST != null) {
237-
var lhsWR = _cache[lhsAST.expression];
238-
if (lhsWR == null) {
239-
lhsWR = _cache[lhsAST.expression] = lhsAST.setupWatch(this);
240-
}
226+
var lhsWR = lhsAST.setupWatch(this);
241227
lhsWR.handler.addForwardHandler(invokeHandler);
242228
invokeHandler.acceptValue(lhsWR.currentValue);
243229
}
244230

245231
// Convert the args from AST to WatchRecords
246232
for (var i = 0; i < argsAST.length; i++) {
247233
var ast = argsAST[i];
248-
WatchRecord<_Handler> record = _cache[ast.expression];
249-
if (record == null) {
250-
record = _cache[ast.expression] = ast.setupWatch(this);
251-
}
234+
WatchRecord<_Handler> record = ast.setupWatch(this);
252235
_ArgHandler handler = new _PositionalArgHandler(this, evalWatchRecord, i);
253236
_ArgHandlerList._add(invokeHandler, handler);
254237
record.handler.addForwardHandler(handler);
255238
handler.acceptValue(record.currentValue);
256239
}
257240

258241
namedArgsAST.forEach((Symbol name, AST ast) {
259-
WatchRecord<_Handler> record = _cache[ast.expression];
260-
if (record == null) {
261-
record = _cache[ast.expression] = ast.setupWatch(this);
262-
}
242+
WatchRecord<_Handler> record = ast.setupWatch(this);
263243
_ArgHandler handler = new _NamedArgHandler(this, evalWatchRecord, name);
264244
_ArgHandlerList._add(invokeHandler, handler);
265245
record.handler.addForwardHandler(handler);
@@ -301,7 +281,6 @@ class WatchGroup implements _EvalWatchList, _WatchGroupList {
301281
this,
302282
_changeDetector.newGroup(),
303283
context == null ? this.context : context,
304-
new HashMap<String, WatchRecord<_Handler>>(),
305284
_rootGroup == null ? this : _rootGroup);
306285
_WatchGroupList._add(this, childGroup);
307286
var marker = childGroup._marker;
@@ -581,7 +560,6 @@ abstract class _Handler implements _LinkedList, _LinkedListItem, _WatchList {
581560
_releaseWatch();
582561
// Remove ourselves from cache, or else new registrations will go to us,
583562
// but we are dead
584-
watchGrp._cache.remove(expression);
585563

586564
if (forwardingHandler != null) {
587565
// TODO(misko): why do we need this check?

test/change_detection/watch_group_spec.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ void main() {
273273
var watch = watchGrp.watch(parse('user'), (v, p) => logger(v));
274274
var watchFirst = watchGrp.watch(parse('user.first'), (v, p) => logger(v));
275275
var watchLast = watchGrp.watch(parse('user.last'), (v, p) => logger(v));
276-
expect(watchGrp.fieldCost).toEqual(3);
276+
expect(watchGrp.fieldCost).toEqual(5);
277277

278278
watchGrp.detectChanges();
279279
expect(logger).toEqual([user1, 'misko', 'hevery']);
@@ -285,7 +285,7 @@ void main() {
285285

286286

287287
watch.remove();
288-
expect(watchGrp.fieldCost).toEqual(3);
288+
expect(watchGrp.fieldCost).toEqual(4);
289289

290290
watchFirst.remove();
291291
expect(watchGrp.fieldCost).toEqual(2);
@@ -863,8 +863,8 @@ void main() {
863863
expect(watchGrp.detectChanges()).toEqual(6);
864864
// expect(logger).toEqual(['0a', '0A', '1a', '1A', '2A', '1b']);
865865
expect(logger).toEqual(['0a', '1a', '1b', '0A', '1A', '2A']); // we go by registration order
866-
expect(watchGrp.fieldCost).toEqual(1);
867-
expect(watchGrp.totalFieldCost).toEqual(4);
866+
expect(watchGrp.fieldCost).toEqual(2);
867+
expect(watchGrp.totalFieldCost).toEqual(6);
868868
logger.clear();
869869

870870
context['a'] = 1;
@@ -876,8 +876,8 @@ void main() {
876876
child1a.remove(); // should also remove child2
877877
expect(watchGrp.detectChanges()).toEqual(3);
878878
expect(logger).toEqual(['0a', '0A', '1b']);
879-
expect(watchGrp.fieldCost).toEqual(1);
880-
expect(watchGrp.totalFieldCost).toEqual(2);
879+
expect(watchGrp.fieldCost).toEqual(2);
880+
expect(watchGrp.totalFieldCost).toEqual(3);
881881
});
882882

883883
it('should remove all method watches in group and group\'s children', () {

0 commit comments

Comments
 (0)