perf: primitive array fast paths
This commit is contained in:
parent
f82e336849
commit
86063aae5a
|
@ -5,6 +5,19 @@ const ArrayProperty = {
|
|||
return [];
|
||||
},
|
||||
define(receiver, key, blueprint) {
|
||||
let isPrimitiveType = false;
|
||||
switch (blueprint.element.type) {
|
||||
case 'bool':
|
||||
case 'int8': case 'uint8':
|
||||
case 'int16': case 'uint16':
|
||||
case 'int32': case 'uint32':
|
||||
case 'float32': case 'float64':
|
||||
case 'string': {
|
||||
isPrimitiveType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const privateKey = `$$${key}`;
|
||||
let coalescing = true;
|
||||
let coalesced;
|
||||
|
@ -42,6 +55,9 @@ const ArrayProperty = {
|
|||
}
|
||||
const api = {
|
||||
[Symbol.iterator]: () => {
|
||||
if (isPrimitiveType) {
|
||||
return receiver[privateKey].values();
|
||||
}
|
||||
const protocol = toJSON().values();
|
||||
return {
|
||||
next: () => {
|
||||
|
@ -61,8 +77,20 @@ const ArrayProperty = {
|
|||
},
|
||||
merge(value) {
|
||||
coalescing = true;
|
||||
for (const elementKey in value) {
|
||||
receiver[key].setAt(elementKey, value[elementKey]);
|
||||
if (isPrimitiveType) {
|
||||
const change = {};
|
||||
for (const elementKey in value) {
|
||||
receiver[privateKey][elementKey] = value[elementKey];
|
||||
change[elementKey] = value[elementKey];
|
||||
}
|
||||
if (receiver.markChange) {
|
||||
receiver[privateKey].markChange(change);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const elementKey in value) {
|
||||
receiver[key].setAt(elementKey, value[elementKey]);
|
||||
}
|
||||
}
|
||||
flushCoalesced();
|
||||
},
|
||||
|
@ -70,21 +98,28 @@ const ArrayProperty = {
|
|||
const elementBlueprint = blueprint.element;
|
||||
let wasCoalescing = coalescing;
|
||||
coalescing = true;
|
||||
if (!(index in receiver[privateKey])) {
|
||||
Properties[elementBlueprint.type].define(
|
||||
receiver[privateKey],
|
||||
index,
|
||||
elementBlueprint,
|
||||
);
|
||||
if (isPrimitiveType) {
|
||||
receiver[privateKey][index] = value;
|
||||
if (receiver.markChange) {
|
||||
receiver[privateKey].markChange({[index]: value});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(index in receiver[privateKey])) {
|
||||
Properties[elementBlueprint.type].define(
|
||||
receiver[privateKey],
|
||||
index,
|
||||
elementBlueprint,
|
||||
);
|
||||
}
|
||||
receiver[privateKey][index] = value;
|
||||
}
|
||||
receiver[privateKey][index] = value;
|
||||
if (!wasCoalescing) {
|
||||
flushCoalesced();
|
||||
}
|
||||
},
|
||||
toJSON,
|
||||
};
|
||||
|
||||
Object.defineProperties(
|
||||
receiver,
|
||||
{
|
||||
|
@ -94,8 +129,21 @@ const ArrayProperty = {
|
|||
return api;
|
||||
},
|
||||
set(value) {
|
||||
coalescing = true;
|
||||
this[privateKey].length = 0;
|
||||
// fast paths
|
||||
if (isPrimitiveType) {
|
||||
coalescing = false;
|
||||
const change = {};
|
||||
for (const elementKey in value) {
|
||||
this[privateKey][elementKey] = value[elementKey];
|
||||
change[elementKey] = value[elementKey];
|
||||
}
|
||||
if (receiver.markChange) {
|
||||
receiver[privateKey].markChange(change);
|
||||
}
|
||||
return;
|
||||
}
|
||||
coalescing = true;
|
||||
for (const elementKey in value) {
|
||||
this[key].setAt(elementKey, value[elementKey]);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user