Files

110 lines
3.6 KiB
JavaScript

const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const { load, collect, sha, versions } = require('./queue-source.cjs')
async function postInput(queue, method, index) {
const data = new Uint8Array(1024 * 1024)
data[0] = index
const ref = new WeakRef(data)
await queue.enqueue('fixture', method, async () => data[0], data.byteLength)
return ref
}
async function postResult(queue, method, index) {
let ref
await queue.enqueue('fixture', method, async () => {
const data = new Uint8Array(1024 * 1024)
data[0] = index
ref = new WeakRef(data)
return { data }
})
assert(ref)
return ref
}
async function lifetime(Queue, candidate, kind, lane, completed, releaseByIdle = false) {
const queue = new Queue(3, 2)
const hold = Promise.withResolvers()
const stuck = queue.enqueue('fixture', 'fixture.hold', () => hold.promise)
const method = lane === 'background' ? 'git.status' : 'fixture.echo'
const refs = []
const before = process.memoryUsage()
for (let i = 0; i < completed; i++) {
refs.push(await (kind === 'input' ? postInput : postResult)(queue, method, i))
}
await collect()
const retainedBeforeCompaction = refs.filter((ref) => ref.deref()).length
const { historyLength, head } = (() => {
const state = queue.queues.get('fixture')
assert(state)
return { historyLength: state[lane].length, head: state[`${lane}Head`] }
})()
assert.equal(queue.retainedCallBytes, 0)
assert.equal(queue.queuedCallCount, 0)
if (candidate || kind === 'input') {
assert.equal(retainedBeforeCompaction, candidate ? 0 : completed)
}
const afterCompleted = process.memoryUsage()
if (releaseByIdle) {
hold.resolve(0)
await stuck
}
const completionsUntilCompaction = releaseByIdle ? 0 : 33 - head
for (let i = 0; i < completionsUntilCompaction; i++) {
await queue.enqueue('fixture', method, async () => 0)
}
await collect()
const retainedAfterCompaction = refs.filter((ref) => ref.deref()).length
assert.equal(retainedAfterCompaction, 0)
hold.resolve(0)
await stuck
await collect()
assert.equal(queue.queues.size, 0)
return {
candidate,
kind,
lane,
completed,
releaseByIdle,
historyLength,
head,
retainedBeforeCompaction,
retainedAfterCompaction,
activeCreditBytesAfterCompleted: 0,
finalQueues: queue.queues.size,
memoryDelta: {
external: afterCompleted.external - before.external,
heapUsed: afterCompleted.heapUsed - before.heapUsed
}
}
}
async function main() {
const reports = []
for (const candidate of [false, true]) {
const Queue = load(candidate)
for (const [kind, lane, completed, releaseByIdle] of [
['input', 'foreground', 8, false],
['input', 'background', 8, false],
['input', 'foreground', 8, true],
['result', 'foreground', 8, false]
]) {
reports.push(await lifetime(Queue, candidate, kind, lane, completed, releaseByIdle))
console.log(JSON.stringify(reports.at(-1)))
}
}
const resultName = process.versions.electron ? 'electron-results.json' : 'results.json'
fs.writeFileSync(
path.join(__dirname, resultName),
`${JSON.stringify({ node: process.version, electron: process.versions.electron ?? null, versions, proofSha256: sha(fs.readFileSync(__filename)), reports }, null, 2)}\n`
)
}
module.exports = { load, collect, sha }
if (require.main === module) {
main().catch((error) => {
console.error(error)
process.exitCode = 1
})
setTimeout(() => {
console.error('fixture timeout')
process.exit(2)
}, 10000).unref()
}