2026-05-18 15:41:01 +00:00
|
|
|
|
import { readFileSync } from 'node:fs'
|
|
|
|
|
|
import { resolve } from 'node:path'
|
2026-03-08 23:58:24 +00:00
|
|
|
|
|
2026-05-03 18:03:40 +00:00
|
|
|
|
import { bench, group, run } from 'mitata'
|
|
|
|
|
|
|
|
|
|
|
|
import { parseFigFile, exportFigFile, initCodec, SceneGraph } from '@open-pencil/core'
|
2026-03-08 23:58:24 +00:00
|
|
|
|
|
2026-05-05 23:22:08 +00:00
|
|
|
|
import { copyFills } from '#core/scene-graph/copy'
|
|
|
|
|
|
|
2026-03-08 23:58:24 +00:00
|
|
|
|
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
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-03-09 05:50:28 +00:00
|
|
|
|
const sampleIds = [...materialGraph.getAllNodes()].slice(0, 1000).map((n) => n.id)
|
2026-03-08 23:58:24 +00:00
|
|
|
|
bench('getNode × 1000 (material3)', () => {
|
2026-03-09 05:50:28 +00:00
|
|
|
|
for (const id of sampleIds) materialGraph.getNode(id)
|
2026-03-08 23:58:24 +00:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
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 = [
|
2026-05-03 18:03:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-03-08 23:58:24 +00:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
bench('structuredClone × 10k', () => {
|
|
|
|
|
|
for (let i = 0; i < 10_000; i++) structuredClone(sampleFills)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-03-09 05:50:28 +00:00
|
|
|
|
bench('copyFills × 10k', () => {
|
|
|
|
|
|
for (let i = 0; i < 10_000; i++) copyFills(sampleFills)
|
2026-03-08 23:58:24 +00:00
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
await run()
|