Revert "perf: micro"

This reverts commit 05350e6ccf.
This commit is contained in:
cha0s 2024-08-01 14:59:52 -05:00
parent 72d114ac74
commit 2e183559ad

View File

@ -2,9 +2,10 @@ import Schema from './schema.js';
export default class Component { export default class Component {
data = [];
ecs; ecs;
Instance; Instance;
instances = {}; map = {};
pool = []; pool = [];
static properties = {}; static properties = {};
static $$schema; static $$schema;
@ -14,6 +15,19 @@ export default class Component {
this.Instance = this.instanceFromSchema(); this.Instance = this.instanceFromSchema();
} }
allocateMany(count) {
const results = [];
while (count > 0) {
results.push(
this.pool.length > 0
? this.pool.pop()
: this.data.push(new this.Instance()) - 1,
)
count -= 1;
}
return results;
}
async create(entityId, values) { async create(entityId, values) {
const [created] = await this.createMany([[entityId, values]]); const [created] = await this.createMany([[entityId, values]]);
return created; return created;
@ -23,28 +37,36 @@ export default class Component {
if (0 === entries.length) { if (0 === entries.length) {
return []; return [];
} }
let {length} = entries; const allocated = this.allocateMany(entries.length);
const allocated = []; const {properties} = this.constructor.schema.specification.concrete;
while (length > 0) { const Schema = this.constructor.schema.constructor;
allocated.push( const keys = Object.keys(properties);
this.pool.length > 0
? this.pool.pop()
: new this.Instance(),
)
length -= 1;
}
const promises = []; const promises = [];
for (const [entityId, values] of entries) { for (let i = 0; i < entries.length; ++i) {
const instance = allocated.pop(); const [entityId, values = {}] = entries[i];
this.instances[entityId] = instance; this.map[entityId] = allocated[i];
instance.entity = entityId; this.data[allocated[i]].entity = entityId;
for (const key in values) { for (let k = 0; k < keys.length; ++k) {
instance[key] = values[key]; const j = keys[k];
const instance = this.data[allocated[i]];
if (j in values) {
instance[j] = values[j];
}
else {
const defaultValue = Schema.defaultValue(properties[j]);
if ('undefined' !== typeof defaultValue) {
instance[j] = defaultValue;
}
}
} }
promises.push(this.load(instance)); promises.push(this.load(this.data[allocated[i]]));
} }
await Promise.all(promises); await Promise.all(promises);
return allocated; const created = [];
for (let i = 0; i < allocated.length; ++i) {
created.push(this.data[allocated[i]]);
}
return created;
} }
deserialize(entityId, view, offset) { deserialize(entityId, view, offset) {
@ -60,19 +82,19 @@ export default class Component {
this.destroyMany([entityId]); this.destroyMany([entityId]);
} }
destroyMany(entityIds) { destroyMany(entities) {
this.freeMany( this.freeMany(
entityIds entities
.map((entityId) => { .map((entityId) => {
if ('undefined' !== typeof this.instances[entityId]) { if ('undefined' !== typeof this.map[entityId]) {
return this.instances[entityId]; return this.map[entityId];
} }
throw new Error(`can't free for non-existent id ${entityId}`); throw new Error(`can't free for non-existent id ${entityId}`);
}), }),
); );
for (const entityId of entityIds) { for (let i = 0; i < entities.length; i++) {
this.instances[entityId].destroy(); this.data[this.map[entities[i]]].destroy();
delete this.instances[entityId]; this.map[entities[i]] = undefined;
} }
} }
@ -88,12 +110,14 @@ export default class Component {
return json; return json;
} }
freeMany(instances) { freeMany(indices) {
this.pool.push(...instances); for (let i = 0; i < indices.length; ++i) {
this.pool.push(indices[i]);
}
} }
get(entityId) { get(entityId) {
return this.instances[entityId]; return this.data[this.map[entityId]];
} }
async insertMany(entities) { async insertMany(entities) {