Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
bmm tests2
(version: 1)
Comparing performance of:
bm1 vs bm2 vs bm3 vs bm4 vs bm5 vs bm6 vs bm7
Created:
one year ago
by:
Registered User
Jump to the latest result
HTML Preparation code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.7/rxjs.umd.js"></script>
Script Preparation code:
function addMutation(idMutations, typeMutations, action, mutation) { const { block } = mutation; const mutations = idMutations[block.id] || new BlockMutations(); idMutations[block.id] = mutations; mutations.add(mutation); const mutations2 = typeMutations[block.type] || new BlockMutations(); typeMutations[block.type] = mutations2; mutations2.add(mutation); } BlockMutations = class BlockMutations { constructor(useFilter) { this.useFilter = useFilter; this.mutations = []; this.idMutations = {}; this.typeMutations = {}; this.actionMutations = []; this.keyedMutations = {}; this.filters = [ mutation => mutation.block.type, ]; } add(mutation) { if (!this.actionMutations[mutation.action]) { this.actionMutations[mutation.action] = []; } this.actionMutations[mutation.action].push(mutation); } finalize() { const { removed, added, updated } = this.actionMutations; this.finalizeOne(removed); this.finalizeOne(added); this.finalizeOne(updated); } finalizeOne(mutations) { const keyedMutations = this.keyedMutations; const filters = this.filters; for (const mutation of mutations) { this.mutations.push(mutation); const { block } = mutation; const ims = this.idMutations[block.id] || (this.idMutations[block.id] = []); ims.push(mutation); if (this.useFilter) { for (const filter of filters) { const key = filter(mutation); if (key) { const mutations = keyedMutations[key] || (keyedMutations[key] = []); mutations.push(mutation); } } } else { const tms = this.typeMutations[block.id] || (this.typeMutations[block.type] = []); tms.push(mutation); } } } dispatch(listeners) { this.finalize(); for (const { callback, condition } of listeners) { if (condition) { const { type, id } = condition; const mutations = type ? (this.useFilter ? this.keyedMutations[type] : this.typeMutations[type]) : id ? this.idMutations[id] : null; if (mutations) { callback(mutations); } } else { callback(this.mutations); } } } } class BlockMutationsIterator { constructor(mutations, firstIndex, indices) { this.mutations = mutations; this.firstIndex = firstIndex; this.indices = indices; this.cursor = -2; } hasNext() { return this.cursor === -2 || this.cursor >= 0; } next() { const cursor = this.cursor === -2 ? this.firstIndex : this.cursor; if (cursor < 0) { return; } const index = this.indices[cursor]; this.cursor = this.indices[cursor + 1]; return this.mutations[index]; } } BlockMutations2 = class BlockMutations2 { constructor(x) { this.mutations = []; this.actionMutationMap = {}; this.idMutationMap = {}; this.typeMutationMap = {}; } add(mutation) { const { action, block } = mutation; const { actionMutationMap, idMutationMap, typeMutationMap } = this; this.mutations.push(mutation); if (!actionMutationMap[action]) { actionMutationMap[action] = []; } actionMutationMap[action].push(mutation); if (!idMutationMap[block.id]) { idMutationMap[block.id] = []; } idMutationMap[block.id].push(mutation); if (!typeMutationMap[block.type]) { typeMutationMap[block.type] = []; } typeMutationMap[block.type].push(mutation); } finalize() {} dispatch(listeners) { const { typeMutationMap, idMutationMap, actionMutationMap } = this; for (const { callback, condition } of listeners) { if (condition) { const { type, id } = condition; if (type) { if (typeMutationMap[type]) { callback(typeMutationMap[type]); } continue; } if (id) { if (idMutationMap[id]) { callback(idMutationMap[id]); } continue; } } else { callback(actionMutationMap); } } } } const DEFAULT_ID = 0; const ACTION_TYPES = { added: 0, removed: 1, updated: 2, moved: 3, }; function updateIndex(index, offset, lasts, keys, firsts, key, action) { const lastIndex = lasts[offset]; const lastActionIndex = lasts[offset + action]; const keyOffset = keys.length; if (lastIndex >= 0) { keys[lastIndex] = keyOffset + 1; keys[lastActionIndex] = keyOffset + 2; } lasts[offset] = keyOffset + 1; lasts[offset + action] = keyOffset + 2; keys[keyOffset] = index; keys[keyOffset + 1] = -1; keys[keyOffset + 2] = -1; if (firsts[offset] === undefined) { firsts[offset] = keyOffset; } if (firsts[offset + action] === undefined) { firsts[offset + action] = keyOffset; } } BlockMutations3 = class BlockMutations3 { constructor() { this.mutations = []; this.idOffsetMap = {}; this.typeOffsetMap = {}; // self, action1, action2, action3, ... this.idFirsts = []; // self, action1, action2, action3, ... this.typeFirsts = []; // self, action1, action2, action3, ... this.idLasts = []; // self, action1, action2, action3, ... this.typeLasts = []; // mutation index, same id (without action) next, same action next, this.ids = []; // mutation index, same type (without action) next, same action next this.types = []; } add(mutation) { const { block, action } = mutation; const { id, type } = block; const index = this.mutations.push(mutation) - 1; const actionIndex = ACTION_TYPES[action] + 1; const idOffset = this.idOffsetMap[id] || (this.idOffsetMap[id] = this.idFirsts.length); const typeOffset = this.typeOffsetMap[type] || (this.typeOffsetMap[type] = this.typeFirsts.length); updateIndex(index, idOffset, this.idLasts, this.ids, this.idFirsts, block.id, actionIndex); updateIndex(index, typeOffset, this.typeLasts, this.types, this.typeFirsts, block.type, actionIndex); } dispatch(listeners) { const { mutations, typeOffsetMap, idOffsetMap, types, ids } = this; for (const { callback, condition } of listeners) { if (condition) { const { type, id } = condition; if (type) { if (typeOffsetMap[type]) { callback(this); } continue; } if (id) { if (idOffsetMap[id]) { callback(this); } continue; } } else { callback(this); } } } } const Subject = rxjs.Subject; const cb = () => {}; class BlockModel { constructor(id, type) { this.id = id; this.type = type; this.update$ = new Subject(); this.attach$ = new Subject(); this.detach$ = new Subject(); this.structUpdate$ = new Subject(); this.destroy$ = new Subject(); this.update$.subscribe(cb); this.attach$.subscribe(cb); this.detach$.subscribe(cb); this.structUpdate$.subscribe(cb); this.destroy$.subscribe(cb); } } blockManager = new class BlockModelManager { constructor() { this.blockModelCreate$ = new Subject(); this.blockModelUpdate$ = new Subject(); this.blockModelAttached$ = new Subject(); this.blockModelDetached$ = new Subject(); this.blockModelDestroy$ = new Subject(); this.blockModelStructUpdate$ = new Subject(); this.blockModelCreate$.subscribe(cb); this.blockModelUpdate$.subscribe(cb); this.blockModelAttached$.subscribe(cb); this.blockModelDetached$.subscribe(cb); this.blockModelDestroy$.subscribe(cb); this.blockModelStructUpdate$.subscribe(cb); } run(blocks) { blocks.forEach(({ block, action }) => { this.process(block, action); }); } process(block, action) { switch (action) { case 'added': this.blockModelCreate$.next({ block }); block.attach$.next({}); this.blockModelAttached$.next({ block }); block.structUpdate$.next({ block }); this.blockModelStructUpdate$.next({ block }); this.blockModelUpdate$.next({ block }); break; case 'removed': block.detach$.next({}); this.blockModelDetached$.next({ block }); block.destroy$.next({}); this.blockModelDestroy$.next({ block }); block.structUpdate$.next({ block }); this.blockModelStructUpdate$.next({ block }); this.blockModelUpdate$.next({ block }); break; case 'updated': block.update$.next({}); this.blockModelUpdate$.next({ block }); break; // case 'moved': // block.detach$.next({}); // this.blockModelDetached$.next({ block }); // block.destroy$.next({}); // this.blockModelDestroy$.next({ block }); // this.blockModelCreate$.next({ block }); // block.attach$.next({}); // this.blockModelAttached$.next({ block }); // block.structUpdate$.next({ block }); // this.blockModelStructUpdate$.next({ block }); // this.blockModelUpdate$.next({ block }); // break; } } } function range(start, end) { const xs = []; for (let i = start; i < end; ++i) { xs[i] = start + i; } return xs; } const counts = [20000]; const actions = ['added', 'removed', 'updated']; const types = range(0, 52).map(i => String.fromCharCode('A'.charCodeAt(0) + i)); const testIds = counts.map(count => range(0, count)); const testBlocks = testIds.map(is => is.map(id => ({ id, type: types[id % types.length] }))); const testActions = testIds.map(is => is.map(i => actions[i % actions.length])); const testListeners = testBlocks.map(blocks => [...blocks, ...blocks].map((block, i) => { return { callback: () => {}, condition: Math.random() < 0.5 ? null : { type: Math.random() < 0.5 ? null : types[i % types.length], id: Math.random() < 0.5 ? null : block.id, }, }; })); const testSubjects = testListeners.map(listeners => { const subject = new Subject(); listeners.forEach(({ callback }) => { subject.subscribe(callback); }); return subject; }); const testBlockModels = testIds.map((is, i) => is.map((id, j) => { const block = new BlockModel(id, types[id % types.length]); return { block, action: testActions[i][j], } })); testForAdd = (index, mutations) => { const blocks = testBlocks[index]; const actions = testActions[index]; blocks.forEach((block, i) => { mutations.add({ action: actions[i], block }); }); }; testForDispatch = (index, mutations) => { const listeners = testListeners[index]; mutations.listeners = listeners; mutations.dispatch(listeners); }; testForSubjects = (index, mutations) => { const subject = testSubjects[index]; mutations.finalize(); subject.next(mutations); }; testForBlockModelSubject = index => { const blocks = testBlockModels[index]; blockManager.run(blocks); };
Tests:
bm1
mutations = new BlockMutations2(); testForAdd(0, mutations); testForDispatch(0, mutations);
bm2
mutations = new BlockMutations(true); testForAdd(0, mutations); testForDispatch(0, mutations);
bm3
mutations = new BlockMutations(false); testForAdd(0, mutations); testForDispatch(0, mutations);
bm4
testForBlockModelSubject(0);
bm5
mutations = new BlockMutations(true); testForAdd(0, mutations); testForSubjects(0, mutations);
bm6
mutations = new BlockMutations2(); testForAdd(0, mutations); testForSubjects(0, mutations);
bm7
mutations = new BlockMutations(false); testForAdd(0, mutations); testForSubjects(0, mutations);
Rendered benchmark preparation results:
Suite status:
<idle, ready to run>
Run tests (7)
Previous results
Fork
Test case name
Result
bm1
bm2
bm3
bm4
bm5
bm6
bm7
Fastest:
N/A
Slowest:
N/A
Latest run results:
Run details:
(Test run date:
one year ago
)
User agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Browser/OS:
Chrome 127 on Mac OS X 10.15.7
View result in a separate tab
Embed
Embed Benchmark Result
Test name
Executions per second
bm1
581.7 Ops/sec
bm2
653.4 Ops/sec
bm3
607.9 Ops/sec
bm4
434.5 Ops/sec
bm5
548.3 Ops/sec
bm6
490.0 Ops/sec
bm7
503.0 Ops/sec
Autogenerated LLM Summary
(model
llama3.2:3b
, generated one year ago):
I'm ready to help! What's the question?
Related benchmarks:
testingelad2
Immutable.Set Union vs Constructing a new plain JS Set
Immutable.Set Union vs Constructing a new plain JS Set - small
Set (Lodash vs Lodash/fp vs Immutable) comp. test
Comments
Confirm delete:
Do you really want to delete benchmark?