Skip to content

Commit db0f0c4

Browse files
committed
perf(change_detection): use object pools not to create unnecessary garbage
1 parent 62f08d3 commit db0f0c4

File tree

4 files changed

+105
-29
lines changed

4 files changed

+105
-29
lines changed

modules/change_detection/src/change_detection_jit_generator.es6

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {
4343
* var address0;
4444
* var city1;
4545
* var change;
46-
* var changes = [];
46+
* var changes = null;
4747
* var temp;
4848
* var context = this.context;
4949
*
@@ -60,14 +60,15 @@ import {
6060
*
6161
* city1 = address0.city;
6262
* if (city1 !== this.city1) {
63-
* changes.push(ChangeDetectionUtil.simpleChangeRecord(this.protos[1].bindingMemento, this.city1, city1));
63+
* changes = ChangeDetectionUtil.addRecord(changes,
64+
* ChangeDetectionUtil.simpleChangeRecord(this.protos[1].bindingMemento, this.city1, city1));
6465
* this.city1 = city1;
6566
* }
6667
*
6768
* if (changes.length > 0) {
6869
* if(throwOnChange) ChangeDetectionUtil.throwOnChange(this.protos[1], changes[0]);
6970
* this.dispatcher.onRecordChange('address.city', changes);
70-
* changes = [];
71+
* changes = null;
7172
* }
7273
* }
7374
*
@@ -144,7 +145,7 @@ ${localDefinitions}
144145
${changeDefinitions}
145146
var ${TEMP_LOCAL};
146147
var ${CHANGE_LOCAL};
147-
var ${CHANGES_LOCAL} = [];
148+
var ${CHANGES_LOCAL} = null;
148149
149150
context = this.context;
150151
${records}
@@ -153,10 +154,10 @@ ${records}
153154

154155
function notifyTemplate(index:number):string{
155156
return `
156-
if (${CHANGES_LOCAL}.length > 0) {
157+
if (${CHANGES_LOCAL} && ${CHANGES_LOCAL}.length > 0) {
157158
if(throwOnChange) ${UTIL}.throwOnChange(${PROTOS_ACCESSOR}[${index}], ${CHANGES_LOCAL}[0]);
158159
${DISPATCHER_ACCESSOR}.onRecordChange(${PROTOS_ACCESSOR}[${index}].groupMemento, ${CHANGES_LOCAL});
159-
${CHANGES_LOCAL} = [];
160+
${CHANGES_LOCAL} = null;
160161
}
161162
`;
162163
}
@@ -166,7 +167,8 @@ function structuralCheckTemplate(selfIndex:number, field:string, context:string,
166167
return `
167168
${CHANGE_LOCAL} = ${UTIL}.structuralCheck(${field}, ${context});
168169
if (${CHANGE_LOCAL}) {
169-
${CHANGES_LOCAL}.push(${UTIL}.changeRecord(${PROTOS_ACCESSOR}[${selfIndex}].bindingMemento, ${CHANGE_LOCAL}));
170+
${CHANGES_LOCAL} = ${UTIL}.addRecord(${CHANGES_LOCAL},
171+
${UTIL}.changeRecord(${PROTOS_ACCESSOR}[${selfIndex}].bindingMemento, ${CHANGE_LOCAL}));
170172
${field} = ${CHANGE_LOCAL}.currentValue;
171173
}
172174
${notify}
@@ -222,7 +224,8 @@ if (${cond}) {
222224
}
223225

224226
function addSimpleChangeRecordTemplate(protoIndex:number, oldValue:string, newValue:string) {
225-
return `${CHANGES_LOCAL}.push(${UTIL}.simpleChangeRecord(${PROTOS_ACCESSOR}[${protoIndex}].bindingMemento, ${oldValue}, ${newValue}));`;
227+
return `${CHANGES_LOCAL} = ${UTIL}.addRecord(${CHANGES_LOCAL},
228+
${UTIL}.simpleChangeRecord(${PROTOS_ACCESSOR}[${protoIndex}].bindingMemento, ${oldValue}, ${newValue}));`;
226229
}
227230

228231

modules/change_detection/src/change_detection_util.js

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,72 @@ export class SimpleChange {
1919
}
2020
}
2121

22+
var _simpleChangesIndex = 0;
23+
var _simpleChanges = [
24+
new SimpleChange(null, null),
25+
new SimpleChange(null, null),
26+
new SimpleChange(null, null),
27+
new SimpleChange(null, null),
28+
new SimpleChange(null, null),
29+
new SimpleChange(null, null),
30+
new SimpleChange(null, null),
31+
new SimpleChange(null, null),
32+
new SimpleChange(null, null),
33+
new SimpleChange(null, null),
34+
new SimpleChange(null, null),
35+
new SimpleChange(null, null),
36+
new SimpleChange(null, null),
37+
new SimpleChange(null, null),
38+
new SimpleChange(null, null),
39+
new SimpleChange(null, null),
40+
new SimpleChange(null, null),
41+
new SimpleChange(null, null),
42+
new SimpleChange(null, null),
43+
new SimpleChange(null, null)
44+
]
45+
46+
var _changeRecordsIndex = 0;
47+
var _changeRecords = [
48+
new ChangeRecord(null, null),
49+
new ChangeRecord(null, null),
50+
new ChangeRecord(null, null),
51+
new ChangeRecord(null, null),
52+
new ChangeRecord(null, null),
53+
new ChangeRecord(null, null),
54+
new ChangeRecord(null, null),
55+
new ChangeRecord(null, null),
56+
new ChangeRecord(null, null),
57+
new ChangeRecord(null, null),
58+
new ChangeRecord(null, null),
59+
new ChangeRecord(null, null),
60+
new ChangeRecord(null, null),
61+
new ChangeRecord(null, null),
62+
new ChangeRecord(null, null),
63+
new ChangeRecord(null, null),
64+
new ChangeRecord(null, null),
65+
new ChangeRecord(null, null),
66+
new ChangeRecord(null, null),
67+
new ChangeRecord(null, null)
68+
]
69+
70+
function _simpleChange(previousValue, currentValue) {
71+
var index = _simpleChangesIndex++ % 20;
72+
var s = _simpleChanges[index];
73+
s.previousValue = previousValue;
74+
s.currentValue = currentValue;
75+
return s;
76+
}
77+
78+
function _changeRecord(bindingMemento, change) {
79+
var index = _changeRecordsIndex++ % 20;
80+
var s = _changeRecords[index];
81+
s.bindingMemento = bindingMemento;
82+
s.change = change;
83+
return s;
84+
}
85+
86+
var _singleElementList = [null];
87+
2288
export class ChangeDetectionUtil {
2389
static unitialized() {
2490
return uninitialized;
@@ -128,11 +194,29 @@ export class ChangeDetectionUtil {
128194
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
129195
}
130196

197+
static simpleChange(previousValue:any, currentValue:any):SimpleChange {
198+
return _simpleChange(previousValue, currentValue);
199+
}
200+
131201
static changeRecord(memento:any, change:any):ChangeRecord {
132-
return new ChangeRecord(memento, change);
202+
return _changeRecord(memento, change);
133203
}
134204

135205
static simpleChangeRecord(memento:any, previousValue:any, currentValue:any):ChangeRecord {
136-
return new ChangeRecord(memento, new SimpleChange(previousValue, currentValue));
206+
return _changeRecord(memento, _simpleChange(previousValue, currentValue));
137207
}
138-
}
208+
209+
static addRecord(updatedRecords:List, changeRecord:ChangeRecord):List {
210+
if (isBlank(updatedRecords)) {
211+
updatedRecords = _singleElementList;
212+
updatedRecords[0] = changeRecord;
213+
214+
} else if (updatedRecords === _singleElementList) {
215+
updatedRecords = [_singleElementList[0], changeRecord];
216+
217+
} else {
218+
ListWrapper.push(updatedRecords, changeRecord);
219+
}
220+
return updatedRecords;
221+
}
222+
}

modules/change_detection/src/dynamic_change_detector.js

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
6262

6363
if (isPresent(change)) {
6464
currentGroup = proto.groupMemento;
65-
updatedRecords = this._addRecord(updatedRecords, proto, change);
65+
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
66+
updatedRecords = ChangeDetectionUtil.addRecord(updatedRecords, record);
6667
}
6768

6869
if (proto.lastInGroup && isPresent(updatedRecords)) {
@@ -100,7 +101,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
100101
this._setChanged(proto, true);
101102

102103
if (proto.lastInBinding) {
103-
return new SimpleChange(prevValue, currValue);
104+
return ChangeDetectionUtil.simpleChange(prevValue, currValue);
104105
} else {
105106
return null;
106107
}
@@ -164,22 +165,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
164165
return change;
165166
}
166167

167-
_addRecord(updatedRecords:List, proto:ProtoRecord, change):List {
168-
// we can use a pool of change records not to create extra garbage
169-
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
170-
if (isBlank(updatedRecords)) {
171-
updatedRecords = _singleElementList;
172-
updatedRecords[0] = record;
173-
174-
} else if (updatedRecords === _singleElementList) {
175-
updatedRecords = [_singleElementList[0], record];
176-
177-
} else {
178-
ListWrapper.push(updatedRecords, record);
179-
}
180-
return updatedRecords;
181-
}
182-
183168
_readContext(proto:ProtoRecord) {
184169
return this.values[proto.contextIndex];
185170
}

modules/change_detection/test/change_detection_spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ export function main() {
5959
expect(dispatcher.log).toEqual(['name=misko']);
6060
dispatcher.clear();
6161

62+
cd.detectChanges();
63+
expect(dispatcher.log).toEqual([]);
64+
dispatcher.clear();
65+
6266
person.name = "Misko";
6367
cd.detectChanges();
6468
expect(dispatcher.log).toEqual(['name=Misko']);

0 commit comments

Comments
 (0)