mirror of
https://github.com/aphrody-labs/opentui.git
synced 2026-10-13 21:08:53 +00:00
bench: time only drawBox in the box benchmark (#1643)
Version 2 of JS Buffer/draw-box-titled-scissored took a checked buffer lease on every iteration to observe one cell. The timed operation became drawBox plus three FFI calls and a new external ArrayBuffer. On Bun the lease was about half of each operation. On Node it made batch times vary by 5% to 9% and failed the 5% inner RSD gate. Version 3 times only drawBox. Each batch checks the last drawn variant once, outside the timed loop, then clears the signal cell so a batch without draws cannot pass on an earlier result.
This commit is contained in:
1 parent
8213fe8b1d
commit
c46fc7ee8a
2 files changed
+21
-15
No files matched your search
@@ -205,7 +205,9 @@ const BOX_BORDER_FG = RGBA.fromInts(96, 165, 250)
|
||||
const BOX_TITLE_FGS = [RGBA.fromInts(250, 204, 21), RGBA.fromInts(52, 211, 153)] as const
|
||||
const BOX_TOP_TITLES = [" Alpha ", " Omega "] as const
|
||||
const BOX_BOTTOM_TITLES = [" Ready ", " Busy! "] as const
|
||||
const BOX_SIGNAL_INDEX = 2 * BOX_BUFFER_WIDTH + 37
|
||||
const BOX_SIGNAL_X = 37
|
||||
const BOX_SIGNAL_Y = 2
|
||||
const BOX_SIGNAL_INDEX = BOX_SIGNAL_Y * BOX_BUFFER_WIDTH + BOX_SIGNAL_X
|
||||
const BOX_SIGNAL_CHARS = [65, 79] as const
|
||||
const BOX_VARIANTS: readonly Parameters<OptimizedBuffer["drawBox"]>[0][] = BOX_TOP_TITLES.map((title, index) => ({
|
||||
x: 2,
|
||||
@@ -228,8 +230,8 @@ function directBoxDrawingCase(): BenchmarkCase {
|
||||
return {
|
||||
category: "JS Buffer",
|
||||
name: "draw-box-titled-scissored",
|
||||
// Version 2 includes a checked lease for each cell observation.
|
||||
workload_version: 2,
|
||||
// Version 3 times only drawBox. Each batch checks the last draw outside the timed loop.
|
||||
workload_version: 3,
|
||||
parameters: {
|
||||
buffer_width: BOX_BUFFER_WIDTH,
|
||||
buffer_height: BOX_BUFFER_HEIGHT,
|
||||
@@ -258,17 +260,14 @@ function directBoxDrawingCase(): BenchmarkCase {
|
||||
|
||||
buffer.clear(BOX_CLEAR_BG)
|
||||
buffer.pushScissorRect(0, 0, 72, BOX_BUFFER_HEIGHT)
|
||||
let observedSignal = 0
|
||||
let expectedSignal = 0
|
||||
let variant = 0
|
||||
let completed = 0
|
||||
let validated = 0
|
||||
|
||||
return {
|
||||
run(iteration) {
|
||||
const variant = iteration & 1
|
||||
variant = iteration & 1
|
||||
buffer.drawBox(BOX_VARIANTS[variant]!)
|
||||
observedSignal = (observedSignal + buffer.withBuffers((cells) => cells.char[BOX_SIGNAL_INDEX]!)) | 0
|
||||
expectedSignal = (expectedSignal + BOX_SIGNAL_CHARS[variant]!) | 0
|
||||
completed++
|
||||
},
|
||||
validateBatch(iterations) {
|
||||
@@ -276,9 +275,13 @@ function directBoxDrawingCase(): BenchmarkCase {
|
||||
if (actual !== iterations) {
|
||||
throw new Error(`draw-box-titled-scissored: completed ${actual} operations, expected ${iterations}`)
|
||||
}
|
||||
if (observedSignal !== expectedSignal) {
|
||||
throw new Error(`draw-box-titled-scissored: observation ${observedSignal}, expected ${expectedSignal}`)
|
||||
const observed = buffer.withBuffers((cells) => cells.char[BOX_SIGNAL_INDEX]!)
|
||||
const expected = BOX_SIGNAL_CHARS[variant]!
|
||||
if (observed !== expected) {
|
||||
throw new Error(`draw-box-titled-scissored: observation ${observed}, expected ${expected}`)
|
||||
}
|
||||
// Clear the signal so a batch without draws cannot pass on the previous batch's cell.
|
||||
buffer.setCell(BOX_SIGNAL_X, BOX_SIGNAL_Y, " ", BOX_BORDER_FG, BOX_CLEAR_BG)
|
||||
validated = completed
|
||||
},
|
||||
teardown() {
|
||||
|
||||
@@ -71,8 +71,8 @@ describe("statistics and manifest", () => {
|
||||
"JS Text/text-buffer-word-wrap-measure",
|
||||
"JS Buffer/draw-box-titled-scissored",
|
||||
])
|
||||
expect(manifest.cases.find(({ name }) => name === "draw-box-titled-scissored")?.workload_version).toBe(2)
|
||||
expect(manifestHash(manifest)).toBe("sha256:a046b0f302d33ad7eacdbe6e0b951f2a60c7b43863acd3f3bfd06c611902f01e")
|
||||
expect(manifest.cases.find(({ name }) => name === "draw-box-titled-scissored")?.workload_version).toBe(3)
|
||||
expect(manifestHash(manifest)).toBe("sha256:41cc6f0856b059d6b77f0575f7cdd7c297ddd9e59b55185f3b7fc1ef4ce7e1d7")
|
||||
expect(manifestHash({ ...manifest, protocol_version: 2 })).not.toBe(manifestHash(manifest))
|
||||
})
|
||||
|
||||
@@ -314,14 +314,17 @@ test("canonical cases perform and validate work across consecutive batches", asy
|
||||
}
|
||||
})
|
||||
|
||||
test("canonical box drawing validation rejects a no-op", async () => {
|
||||
test("canonical box drawing validation rejects a batch of no-ops", async () => {
|
||||
const benchmark = defaultBenchmarkCases.find(({ name }) => name === "draw-box-titled-scissored")!
|
||||
const runtime = await benchmark.setup()
|
||||
const drawBox = OptimizedBuffer.prototype.drawBox
|
||||
OptimizedBuffer.prototype.drawBox = () => {}
|
||||
try {
|
||||
runtime.run(0)
|
||||
expect(() => runtime.validateBatch(1)).toThrow("draw-box-titled-scissored: observation")
|
||||
runtime.validateBatch(1)
|
||||
OptimizedBuffer.prototype.drawBox = () => {}
|
||||
runtime.run(1)
|
||||
runtime.run(2)
|
||||
expect(() => runtime.validateBatch(2)).toThrow("draw-box-titled-scissored: observation")
|
||||
} finally {
|
||||
OptimizedBuffer.prototype.drawBox = drawBox
|
||||
await runtime.teardown()
|
||||
|
||||
Reference in new issue
Block a user