test: T29-T31 component tests (20) + frontend stresstest (7) + backend DB stresstest (6) with 50k elements
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Stresstest – 50.000 Elemente: SpatialIndex Query-Performance,
|
||||
* HistoryManager Memory, Undo/Redo Performance.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { SpatialIndex } from '../src/canvas/SpatialIndex';
|
||||
import { HistoryManager } from '../src/history/HistoryManager';
|
||||
import type { CADElement, CADLayer } from '../src/types/cad.types';
|
||||
|
||||
const N = 50_000;
|
||||
|
||||
function generateElements(count: number): CADElement[] {
|
||||
const elements: CADElement[] = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
elements.push({
|
||||
id: `elem-${i}`,
|
||||
type: 'rect',
|
||||
layerId: 'layer-1',
|
||||
x: (i % 1000) * 1.5,
|
||||
y: Math.floor(i / 1000) * 1.5,
|
||||
width: 1,
|
||||
height: 1,
|
||||
properties: {},
|
||||
});
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
function makeLayer(): CADLayer {
|
||||
return {
|
||||
id: 'layer-1',
|
||||
name: 'Layer 1',
|
||||
visible: true,
|
||||
locked: false,
|
||||
color: '#ffffff',
|
||||
lineType: 'solid',
|
||||
transparency: 0,
|
||||
sortOrder: 0,
|
||||
parentId: null,
|
||||
};
|
||||
}
|
||||
|
||||
describe('Stresstest: 50.000 Elemente', () => {
|
||||
it('should bulk-insert 50k elements into SpatialIndex in under 2s', () => {
|
||||
const elements = generateElements(N);
|
||||
const index = new SpatialIndex();
|
||||
const start = performance.now();
|
||||
index.bulkInsert(elements);
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`SpatialIndex bulkInsert: ${elapsed.toFixed(1)}ms for ${N} elements`);
|
||||
expect(elapsed).toBeLessThan(2000);
|
||||
});
|
||||
|
||||
it('should search SpatialIndex with 50k elements in under 10ms', () => {
|
||||
const elements = generateElements(N);
|
||||
const index = new SpatialIndex();
|
||||
index.bulkInsert(elements);
|
||||
// Search a region in the middle
|
||||
const start = performance.now();
|
||||
const results = index.search({ minX: 750, minY: 37.5, maxX: 1500, maxY: 75 });
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`SpatialIndex search: ${elapsed.toFixed(2)}ms, found ${results.length} elements`);
|
||||
expect(elapsed).toBeLessThan(50);
|
||||
expect(results.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should search a small point region with 50k elements in under 5ms', () => {
|
||||
const elements = generateElements(N);
|
||||
const index = new SpatialIndex();
|
||||
index.bulkInsert(elements);
|
||||
const start = performance.now();
|
||||
const results = index.search({ minX: 750, minY: 37.5, maxX: 751, maxY: 38.5 });
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`SpatialIndex point search: ${elapsed.toFixed(3)}ms, found ${results.length} elements`);
|
||||
expect(elapsed).toBeLessThan(10);
|
||||
});
|
||||
|
||||
it('should clear and re-insert 50k elements in under 2s', () => {
|
||||
const elements = generateElements(N);
|
||||
const index = new SpatialIndex();
|
||||
index.bulkInsert(elements);
|
||||
// Modify 100 elements
|
||||
for (let i = 0; i < 100; i++) {
|
||||
elements[i].x += 5000;
|
||||
}
|
||||
const start = performance.now();
|
||||
index.clear();
|
||||
index.bulkInsert(elements);
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`SpatialIndex clear+reinsert: ${elapsed.toFixed(1)}ms after 100 modifications`);
|
||||
expect(elapsed).toBeLessThan(2000);
|
||||
});
|
||||
|
||||
it('should handle HistoryManager with 50k elements snapshot', () => {
|
||||
const elements = generateElements(N);
|
||||
const layers = [makeLayer()];
|
||||
const history = new HistoryManager({ maxStackSize: 50 });
|
||||
const start = performance.now();
|
||||
history.initialize({
|
||||
elements,
|
||||
layers,
|
||||
blocks: [],
|
||||
groups: [],
|
||||
bgConfig: null,
|
||||
});
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`HistoryManager initialize: ${elapsed.toFixed(1)}ms for ${N} elements`);
|
||||
expect(elapsed).toBeLessThan(1000);
|
||||
});
|
||||
|
||||
it('should push 10 history snapshots with 50k elements each', () => {
|
||||
const elements = generateElements(N);
|
||||
const layers = [makeLayer()];
|
||||
const history = new HistoryManager({ maxStackSize: 50 });
|
||||
history.initialize({
|
||||
elements,
|
||||
layers,
|
||||
blocks: [],
|
||||
groups: [],
|
||||
bgConfig: null,
|
||||
});
|
||||
const start = performance.now();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
// Slightly modify elements each snapshot
|
||||
elements[i * 100].x += 1;
|
||||
history.pushSnapshot({
|
||||
elements: [...elements],
|
||||
layers,
|
||||
blocks: [],
|
||||
groups: [],
|
||||
bgConfig: null,
|
||||
label: `Step ${i + 1}`,
|
||||
});
|
||||
}
|
||||
const elapsed = performance.now() - start;
|
||||
console.log(`HistoryManager 10 snapshots: ${elapsed.toFixed(1)}ms for ${N} elements each`);
|
||||
expect(elapsed).toBeLessThan(5000);
|
||||
expect(history.getHistory().length).toBe(11); // initial + 10
|
||||
});
|
||||
|
||||
it('should undo/redo with 50k elements in under 100ms', () => {
|
||||
const elements = generateElements(N);
|
||||
const layers = [makeLayer()];
|
||||
const history = new HistoryManager({ maxStackSize: 50 });
|
||||
history.initialize({
|
||||
elements,
|
||||
layers,
|
||||
blocks: [],
|
||||
groups: [],
|
||||
bgConfig: null,
|
||||
});
|
||||
history.pushSnapshot({
|
||||
elements: [...elements],
|
||||
layers,
|
||||
blocks: [],
|
||||
groups: [],
|
||||
bgConfig: null,
|
||||
label: 'Step 1',
|
||||
});
|
||||
const undoStart = performance.now();
|
||||
const undoSnap = history.undo();
|
||||
const undoTime = performance.now() - undoStart;
|
||||
console.log(`Undo: ${undoTime.toFixed(2)}ms for ${N} elements`);
|
||||
expect(undoSnap).not.toBeNull();
|
||||
expect(undoTime).toBeLessThan(100);
|
||||
const redoStart = performance.now();
|
||||
const redoSnap = history.redo();
|
||||
const redoTime = performance.now() - redoStart;
|
||||
console.log(`Redo: ${redoTime.toFixed(2)}ms for ${N} elements`);
|
||||
expect(redoSnap).not.toBeNull();
|
||||
expect(redoTime).toBeLessThan(100);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user