mirror of
https://github.com/stablyai/orca.git
synced 2026-09-27 08:02:35 +00:00
perf: bound raw Markdown document-link closing searches
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { performance } from 'node:perf_hooks'
|
||||
import { build } from 'esbuild'
|
||||
import { buildCounterbalancedSchedule } from './counterbalanced-benchmark-schedule.mjs'
|
||||
|
||||
const baseline = process.argv[2] ?? '20ab9950654'
|
||||
const file = 'src/renderer/src/components/editor/raw-markdown-html.ts'
|
||||
async function load(contents) {
|
||||
const result = await build({
|
||||
stdin: {
|
||||
contents: `${contents}\nexport { createRichMarkdownEditorCodec } from './rich-markdown-source-transport'`,
|
||||
loader: 'ts',
|
||||
resolveDir: dirname(resolve(file))
|
||||
},
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
format: 'esm',
|
||||
write: false,
|
||||
banner: {
|
||||
js: `import { createRequire } from 'node:module'; const require = createRequire(${JSON.stringify(resolve('package.json'))});`
|
||||
}
|
||||
})
|
||||
return import(
|
||||
`data:text/javascript;base64,${Buffer.from(result.outputFiles[0].text).toString('base64')}`
|
||||
)
|
||||
}
|
||||
const arms = {
|
||||
before: await load(
|
||||
execFileSync('git', ['show', `${baseline}:${file}`], { encoding: 'utf8', windowsHide: true })
|
||||
),
|
||||
after: await load(readFileSync(file, 'utf8'))
|
||||
}
|
||||
const key = '0123456789abcdef0123456789abcdef'
|
||||
const codecs = Object.fromEntries(
|
||||
Object.entries(arms).map(([arm, module]) => [arm, module.createRichMarkdownEditorCodec(key)])
|
||||
)
|
||||
const results = []
|
||||
for (const [name, input] of [
|
||||
['plain', '# Heading\nOrdinary prose.'],
|
||||
['complete', 'prefix [[README.md]] text '.repeat(100)],
|
||||
['unclosed-1000', `prefix ${'[[x'.repeat(1000)}`],
|
||||
['unclosed-8000', `prefix ${'[[x'.repeat(8000)} <b>tail</b>`],
|
||||
['invalid-closed-8000', `prefix ${'[[x'.repeat(8000)}]]`],
|
||||
['authored-1000', `prefix ${`[[ORCA_RICH_MD:${key}:`.repeat(1000)}`],
|
||||
['protected', '\\[[README.md]] `[[code.md]]`\n```md\n[[fenced.md]]\n```\n[[tail'],
|
||||
['transport', `before [[ORCA_RICH_MD:${key}:literal:hello]] [[tail`]
|
||||
]) {
|
||||
for (const htmlSuperscriptLinks of [false, true]) {
|
||||
const options = { htmlSuperscriptLinks }
|
||||
const invoke = (arm) =>
|
||||
arms[arm].encodeRawMarkdownHtmlForRichEditor(input, codecs[arm], options)
|
||||
assert.equal(invoke('after'), invoke('before'))
|
||||
const iterations = name.includes('8000') || name.includes('1000') ? 2 : 100
|
||||
function run(arm) {
|
||||
global.gc?.()
|
||||
const start = performance.now()
|
||||
const cpuStart = process.cpuUsage()
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
invoke(arm)
|
||||
}
|
||||
const cpu = process.cpuUsage(cpuStart)
|
||||
return {
|
||||
ms: (performance.now() - start) / iterations,
|
||||
cpuMs: (cpu.user + cpu.system) / 1000 / iterations
|
||||
}
|
||||
}
|
||||
run('before')
|
||||
run('after')
|
||||
const samples = { before: [], after: [] }
|
||||
for (const pair of buildCounterbalancedSchedule(10, 'before', 'after')) {
|
||||
for (const arm of pair) {
|
||||
samples[arm].push(run(arm))
|
||||
}
|
||||
}
|
||||
const median = (values) => {
|
||||
const sorted = [...values].sort((a, b) => a - b)
|
||||
return (sorted[4] + sorted[5]) / 2
|
||||
}
|
||||
results.push({
|
||||
name,
|
||||
htmlSuperscriptLinks,
|
||||
beforeCpuMs: median(samples.before.map((s) => s.cpuMs)),
|
||||
afterCpuMs: median(samples.after.map((s) => s.cpuMs)),
|
||||
beforeMs: median(samples.before.map((s) => s.ms)),
|
||||
afterMs: median(samples.after.map((s) => s.ms)),
|
||||
samples
|
||||
})
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
JSON.stringify({ baseline, node: process.version, platform: process.platform, results }, null, 2)
|
||||
)
|
||||
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { encodeRawMarkdownHtmlForRichEditor } from './raw-markdown-html'
|
||||
import { createRichMarkdownEditorCodec } from './rich-markdown-source-transport'
|
||||
|
||||
const key = '0123456789abcdef0123456789abcdef'
|
||||
|
||||
describe('raw Markdown document-link closing searches', () => {
|
||||
it.each([false, true])('skips impossible suffix searches (superscript links: %s)', (enabled) => {
|
||||
const codec = createRichMarkdownEditorCodec(key)
|
||||
const suffix = '[[missing '.repeat(300)
|
||||
const input = `prefix [[README.md]] ${suffix}`
|
||||
const original = String.prototype.indexOf
|
||||
let searches = 0
|
||||
const spy = vi.spyOn(String.prototype, 'indexOf').mockImplementation(function (
|
||||
this: string,
|
||||
search: string,
|
||||
position?: number
|
||||
) {
|
||||
if (search === ']]') {
|
||||
searches++
|
||||
}
|
||||
return original.call(this, search, position)
|
||||
})
|
||||
let output: string
|
||||
try {
|
||||
output = encodeRawMarkdownHtmlForRichEditor(input, codec, { htmlSuperscriptLinks: enabled })
|
||||
} finally {
|
||||
spy.mockRestore()
|
||||
}
|
||||
expect(output).toBe(`prefix ${codec.transport.create('document-link', 'README.md')} ${suffix}`)
|
||||
expect(searches).toBe(1)
|
||||
})
|
||||
|
||||
it('protects every unclosed authored prefix without rescanning the suffix', () => {
|
||||
const codec = createRichMarkdownEditorCodec(key)
|
||||
const prefix = codec.transport.authoredPrefix
|
||||
const input = `before ${`${prefix}x `.repeat(300)}`
|
||||
const spy = vi.spyOn(String.prototype, 'indexOf')
|
||||
let output: string
|
||||
let searches: number
|
||||
try {
|
||||
output = encodeRawMarkdownHtmlForRichEditor(input, codec)
|
||||
searches = spy.mock.calls.filter(([search]) => search === ']]').length
|
||||
} finally {
|
||||
spy.mockRestore()
|
||||
}
|
||||
expect(output).toBe(`before ${`${codec.transport.create('literal', prefix)}x `.repeat(300)}`)
|
||||
expect(searches).toBe(0)
|
||||
})
|
||||
|
||||
it('preserves escaped and code-protected links around the final closing marker', () => {
|
||||
const codec = createRichMarkdownEditorCodec(key)
|
||||
const input = '\\[[README.md]] `[[inline.md]]`\n```md\n[[fenced.md]]\n```\n[[unclosed'
|
||||
expect(encodeRawMarkdownHtmlForRichEditor(input, codec)).toBe(input)
|
||||
})
|
||||
|
||||
it('preserves a complete authored envelope before an unclosed document link', () => {
|
||||
const codec = createRichMarkdownEditorCodec(key)
|
||||
const authored = `${codec.transport.authoredPrefix}literal:hello]]`
|
||||
expect(encodeRawMarkdownHtmlForRichEditor(`before ${authored} [[tail`, codec)).toBe(
|
||||
`before ${codec.transport.create('literal', authored)} [[tail`
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -59,6 +59,7 @@ export function encodeRawMarkdownHtmlForRichEditor(
|
||||
{ htmlSuperscriptLinks = false }: { htmlSuperscriptLinks?: boolean } = {}
|
||||
): string {
|
||||
const normalizedContent = normalizeMarkdownReferenceLinks(content)
|
||||
const lastBracketClose = normalizedContent.lastIndexOf(']]')
|
||||
const { transport } = codec
|
||||
let index = 0
|
||||
let isLineStart = true
|
||||
@@ -156,7 +157,10 @@ export function encodeRawMarkdownHtmlForRichEditor(
|
||||
// Why: authored text that happens to contain this editor's random envelope
|
||||
// prefix must remain literal even in HTML-free documents and after edits.
|
||||
if (normalizedContent.startsWith(transport.authoredPrefix, index)) {
|
||||
const authoredEnd = normalizedContent.indexOf(']]', index + transport.authoredPrefix.length)
|
||||
const authoredEnd =
|
||||
index + transport.authoredPrefix.length > lastBracketClose
|
||||
? -1
|
||||
: normalizedContent.indexOf(']]', index + transport.authoredPrefix.length)
|
||||
const authoredOccurrence =
|
||||
authoredEnd === -1
|
||||
? transport.authoredPrefix
|
||||
@@ -190,7 +194,8 @@ export function encodeRawMarkdownHtmlForRichEditor(
|
||||
normalizedContent[index + 1] === '[' &&
|
||||
!isEscaped(normalizedContent, index)
|
||||
) {
|
||||
const closingIndex = normalizedContent.indexOf(']]', index + 2)
|
||||
const closingIndex =
|
||||
index + 2 > lastBracketClose ? -1 : normalizedContent.indexOf(']]', index + 2)
|
||||
if (closingIndex !== -1) {
|
||||
const rawTarget = normalizedContent.slice(index + 2, closingIndex)
|
||||
const link = parseMarkdownDocLink(rawTarget)
|
||||
|
||||
Reference in New Issue
Block a user