perf(change_detection): use object pools not to create unnecessary garbage
This commit is contained in:
parent
62f08d38db
commit
db0f0c462b
|
@ -43,7 +43,7 @@ import {
|
|||
* var address0;
|
||||
* var city1;
|
||||
* var change;
|
||||
* var changes = [];
|
||||
* var changes = null;
|
||||
* var temp;
|
||||
* var context = this.context;
|
||||
*
|
||||
|
@ -60,14 +60,15 @@ import {
|
|||
*
|
||||
* city1 = address0.city;
|
||||
* if (city1 !== this.city1) {
|
||||
* changes.push(ChangeDetectionUtil.simpleChangeRecord(this.protos[1].bindingMemento, this.city1, city1));
|
||||
* changes = ChangeDetectionUtil.addRecord(changes,
|
||||
* ChangeDetectionUtil.simpleChangeRecord(this.protos[1].bindingMemento, this.city1, city1));
|
||||
* this.city1 = city1;
|
||||
* }
|
||||
*
|
||||
* if (changes.length > 0) {
|
||||
* if(throwOnChange) ChangeDetectionUtil.throwOnChange(this.protos[1], changes[0]);
|
||||
* this.dispatcher.onRecordChange('address.city', changes);
|
||||
* changes = [];
|
||||
* changes = null;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
|
@ -144,7 +145,7 @@ ${localDefinitions}
|
|||
${changeDefinitions}
|
||||
var ${TEMP_LOCAL};
|
||||
var ${CHANGE_LOCAL};
|
||||
var ${CHANGES_LOCAL} = [];
|
||||
var ${CHANGES_LOCAL} = null;
|
||||
|
||||
context = this.context;
|
||||
${records}
|
||||
|
@ -153,10 +154,10 @@ ${records}
|
|||
|
||||
function notifyTemplate(index:number):string{
|
||||
return `
|
||||
if (${CHANGES_LOCAL}.length > 0) {
|
||||
if (${CHANGES_LOCAL} && ${CHANGES_LOCAL}.length > 0) {
|
||||
if(throwOnChange) ${UTIL}.throwOnChange(${PROTOS_ACCESSOR}[${index}], ${CHANGES_LOCAL}[0]);
|
||||
${DISPATCHER_ACCESSOR}.onRecordChange(${PROTOS_ACCESSOR}[${index}].groupMemento, ${CHANGES_LOCAL});
|
||||
${CHANGES_LOCAL} = [];
|
||||
${CHANGES_LOCAL} = null;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -166,7 +167,8 @@ function structuralCheckTemplate(selfIndex:number, field:string, context:string,
|
|||
return `
|
||||
${CHANGE_LOCAL} = ${UTIL}.structuralCheck(${field}, ${context});
|
||||
if (${CHANGE_LOCAL}) {
|
||||
${CHANGES_LOCAL}.push(${UTIL}.changeRecord(${PROTOS_ACCESSOR}[${selfIndex}].bindingMemento, ${CHANGE_LOCAL}));
|
||||
${CHANGES_LOCAL} = ${UTIL}.addRecord(${CHANGES_LOCAL},
|
||||
${UTIL}.changeRecord(${PROTOS_ACCESSOR}[${selfIndex}].bindingMemento, ${CHANGE_LOCAL}));
|
||||
${field} = ${CHANGE_LOCAL}.currentValue;
|
||||
}
|
||||
${notify}
|
||||
|
@ -222,7 +224,8 @@ if (${cond}) {
|
|||
}
|
||||
|
||||
function addSimpleChangeRecordTemplate(protoIndex:number, oldValue:string, newValue:string) {
|
||||
return `${CHANGES_LOCAL}.push(${UTIL}.simpleChangeRecord(${PROTOS_ACCESSOR}[${protoIndex}].bindingMemento, ${oldValue}, ${newValue}));`;
|
||||
return `${CHANGES_LOCAL} = ${UTIL}.addRecord(${CHANGES_LOCAL},
|
||||
${UTIL}.simpleChangeRecord(${PROTOS_ACCESSOR}[${protoIndex}].bindingMemento, ${oldValue}, ${newValue}));`;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,72 @@ export class SimpleChange {
|
|||
}
|
||||
}
|
||||
|
||||
var _simpleChangesIndex = 0;
|
||||
var _simpleChanges = [
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null),
|
||||
new SimpleChange(null, null)
|
||||
]
|
||||
|
||||
var _changeRecordsIndex = 0;
|
||||
var _changeRecords = [
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null),
|
||||
new ChangeRecord(null, null)
|
||||
]
|
||||
|
||||
function _simpleChange(previousValue, currentValue) {
|
||||
var index = _simpleChangesIndex++ % 20;
|
||||
var s = _simpleChanges[index];
|
||||
s.previousValue = previousValue;
|
||||
s.currentValue = currentValue;
|
||||
return s;
|
||||
}
|
||||
|
||||
function _changeRecord(bindingMemento, change) {
|
||||
var index = _changeRecordsIndex++ % 20;
|
||||
var s = _changeRecords[index];
|
||||
s.bindingMemento = bindingMemento;
|
||||
s.change = change;
|
||||
return s;
|
||||
}
|
||||
|
||||
var _singleElementList = [null];
|
||||
|
||||
export class ChangeDetectionUtil {
|
||||
static unitialized() {
|
||||
return uninitialized;
|
||||
|
@ -128,11 +194,29 @@ export class ChangeDetectionUtil {
|
|||
throw new ExpressionChangedAfterItHasBeenChecked(proto, change);
|
||||
}
|
||||
|
||||
static simpleChange(previousValue:any, currentValue:any):SimpleChange {
|
||||
return _simpleChange(previousValue, currentValue);
|
||||
}
|
||||
|
||||
static changeRecord(memento:any, change:any):ChangeRecord {
|
||||
return new ChangeRecord(memento, change);
|
||||
return _changeRecord(memento, change);
|
||||
}
|
||||
|
||||
static simpleChangeRecord(memento:any, previousValue:any, currentValue:any):ChangeRecord {
|
||||
return new ChangeRecord(memento, new SimpleChange(previousValue, currentValue));
|
||||
return _changeRecord(memento, _simpleChange(previousValue, currentValue));
|
||||
}
|
||||
|
||||
static addRecord(updatedRecords:List, changeRecord:ChangeRecord):List {
|
||||
if (isBlank(updatedRecords)) {
|
||||
updatedRecords = _singleElementList;
|
||||
updatedRecords[0] = changeRecord;
|
||||
|
||||
} else if (updatedRecords === _singleElementList) {
|
||||
updatedRecords = [_singleElementList[0], changeRecord];
|
||||
|
||||
} else {
|
||||
ListWrapper.push(updatedRecords, changeRecord);
|
||||
}
|
||||
return updatedRecords;
|
||||
}
|
||||
}
|
|
@ -62,7 +62,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
|||
|
||||
if (isPresent(change)) {
|
||||
currentGroup = proto.groupMemento;
|
||||
updatedRecords = this._addRecord(updatedRecords, proto, change);
|
||||
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
|
||||
updatedRecords = ChangeDetectionUtil.addRecord(updatedRecords, record);
|
||||
}
|
||||
|
||||
if (proto.lastInGroup && isPresent(updatedRecords)) {
|
||||
|
@ -100,7 +101,7 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
|||
this._setChanged(proto, true);
|
||||
|
||||
if (proto.lastInBinding) {
|
||||
return new SimpleChange(prevValue, currValue);
|
||||
return ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -164,22 +165,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
|||
return change;
|
||||
}
|
||||
|
||||
_addRecord(updatedRecords:List, proto:ProtoRecord, change):List {
|
||||
// we can use a pool of change records not to create extra garbage
|
||||
var record = ChangeDetectionUtil.changeRecord(proto.bindingMemento, change);
|
||||
if (isBlank(updatedRecords)) {
|
||||
updatedRecords = _singleElementList;
|
||||
updatedRecords[0] = record;
|
||||
|
||||
} else if (updatedRecords === _singleElementList) {
|
||||
updatedRecords = [_singleElementList[0], record];
|
||||
|
||||
} else {
|
||||
ListWrapper.push(updatedRecords, record);
|
||||
}
|
||||
return updatedRecords;
|
||||
}
|
||||
|
||||
_readContext(proto:ProtoRecord) {
|
||||
return this.values[proto.contextIndex];
|
||||
}
|
||||
|
|
|
@ -59,6 +59,10 @@ export function main() {
|
|||
expect(dispatcher.log).toEqual(['name=misko']);
|
||||
dispatcher.clear();
|
||||
|
||||
cd.detectChanges();
|
||||
expect(dispatcher.log).toEqual([]);
|
||||
dispatcher.clear();
|
||||
|
||||
person.name = "Misko";
|
||||
cd.detectChanges();
|
||||
expect(dispatcher.log).toEqual(['name=Misko']);
|
||||
|
|
Loading…
Reference in New Issue