openpencil/tests/engine/perf.bench.ts
Danila Poyarkov 07674d1919 Restructure @open-pencil/core into domain modules
Move 30+ loose files at src/ root into domain directories:
- scene-graph/ — SceneGraph class, instances, hit-test, copy, snap, undo
- color/ — parse/format, color management, OkHCL
- text/ — text editor, style runs, direction, fonts
- vector/ — vector network encode/decode, bezier math
- figma-api/ — FigmaAPI class, FigmaNodeProxy
- icons/ — Iconify API client, icon rendering
- canvas/ — SkiaRenderer (was renderer/)
- design-jsx/ — JSX-to-design renderer (was render/)

Also:
- Move fig-compress.ts into io/formats/fig/compress.ts
- Delete re-export shims (headless-render.ts, svg-export/)
- Convert all self-referencing @open-pencil/core/* imports to relative
- Clean up package.json exports (26 subpaths, no internal leaks)
- Update AGENTS.md subpath table

Fixes #179
2026-04-06 14:39:53 +03:00

95 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { bench, group, run } from 'mitata'
import { readFileSync } from 'fs'
import { resolve } from 'path'
import { parseFigFile, exportFigFile, initCodec, SceneGraph } from '@open-pencil/core'
import { copyFills } from '../../packages/core/src/scene-graph/copy'
const FIXTURES = resolve(import.meta.dir, '../fixtures')
const goldBuf = readFileSync(resolve(FIXTURES, 'gold-preview.fig'))
const materialBuf = readFileSync(resolve(FIXTURES, 'material3.fig'))
await initCodec()
group('parseFigFile', () => {
bench('gold-preview.fig (537K)', async () => {
await parseFigFile(goldBuf.buffer.slice(0) as ArrayBuffer)
})
bench('material3.fig (55M)', async () => {
await parseFigFile(materialBuf.buffer.slice(0) as ArrayBuffer)
})
})
const goldGraph = await parseFigFile(goldBuf.buffer.slice(0) as ArrayBuffer)
const materialGraph = await parseFigFile(materialBuf.buffer.slice(0) as ArrayBuffer)
group('exportFigFile', () => {
bench('gold-preview', async () => {
await exportFigFile(goldGraph)
})
bench('material3', async () => {
await exportFigFile(materialGraph)
})
})
group('SceneGraph operations', () => {
bench('getAllNodes (material3)', () => {
const nodes = [...materialGraph.getAllNodes()]
void nodes.length
})
const sampleIds = [...materialGraph.getAllNodes()].slice(0, 1000).map((n) => n.id)
bench('getNode × 1000 (material3)', () => {
for (const id of sampleIds) materialGraph.getNode(id)
})
bench('createNode + deleteNode × 100', () => {
const graph = new SceneGraph()
const page = graph.getPages()[0]
const ids: string[] = []
for (let i = 0; i < 100; i++) {
const node = graph.createNode('RECTANGLE', page.id, {
name: `R${i}`,
width: 50,
height: 50
})
ids.push(node.id)
}
for (const id of ids) graph.deleteNode(id)
})
})
group('SceneNode memory', () => {
bench('create 10k nodes', () => {
const graph = new SceneGraph()
const page = graph.getPages()[0]
for (let i = 0; i < 10_000; i++) {
graph.createNode('RECTANGLE', page.id, {
name: `R${i}`,
width: 50,
height: 50
})
}
})
})
group('structuredClone vs copy (fills)', () => {
const sampleFills = [
{ type: 'SOLID' as const, color: { r: 1, g: 0, b: 0, a: 1 }, opacity: 1, visible: true, blendMode: 'NORMAL' as const },
{ type: 'SOLID' as const, color: { r: 0, g: 1, b: 0, a: 1 }, opacity: 0.5, visible: true, blendMode: 'NORMAL' as const }
]
bench('structuredClone × 10k', () => {
for (let i = 0; i < 10_000; i++) structuredClone(sampleFills)
})
bench('copyFills × 10k', () => {
for (let i = 0; i < 10_000; i++) copyFills(sampleFills)
})
})
await run()