Rebuild: XOVER replies are joined once, when complete
Test and deploy / test (push) Successful in 21s
Test and deploy / deploy (push) Skipped

XoverClient joined all received pieces into one buffer on every arrival
(quadratic for a 2.6 MB reply), and turned the inflated check into text
the raw path doesn't use. The coordinator under load (3 workers, 4
connections): busy 40% → 13% of a core, Buffer.concat gone from the
profile. (master's relay uses the same client.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-09 01:36:28 +02:00
1 parent ead2790515
commit 08c876b690
1 file changed
+25 -8
+25 -8
View File
@@ -118,7 +118,7 @@ export class XoverClient {
const reply = await this.command(`XOVER ${from}-${to}`)
if (reply.startsWith('420') || reply.startsWith('423')) return deflateSync(Buffer.alloc(0))
await this.expect(reply, ['224'])
if (reply.includes('COMPRESS=GZIP')) return (await this.compressedRaw()).raw
if (reply.includes('COMPRESS=GZIP')) return (await this.compressedRaw(false)).raw
// Plain replies (the relay's default): compressed off the event loop, at the fastest level.
return deflateAsync(Buffer.from(await this.plainBody()), { level: 1 })
})
@@ -214,19 +214,36 @@ export class XoverClient {
}
private async compressedBody(): Promise<string> {
return (await this.compressedRaw()).text
return (await this.compressedRaw(true)).text
}
/** A zlib/gzip stream followed by a "." line: complete once it ends in ".\r\n" and inflates. */
private async compressedRaw(): Promise<{ raw: Buffer; text: string }> {
/** Whether what was received so far ends in `tail`, without joining the pieces. */
private endsWith(tail: Buffer): boolean {
if (this.length < tail.length) return false
let need = tail.length
for (let i = this.chunks.length - 1; i >= 0 && need > 0; i--) {
const chunk = this.chunks[i]
const n = Math.min(need, chunk.length)
if (!chunk.subarray(chunk.length - n).equals(tail.subarray(need - n, need))) return false
need -= n
}
return need === 0
}
/**
* A zlib/gzip stream followed by a "." line: complete once it ends in
* ".\r\n" and inflates. The pieces are joined only then: joining them on
* every arrival was quadratic, ~15% of a prefetcher's time (LOG.md 2026-10-09).
*/
private async compressedRaw(wantText: boolean): Promise<{ raw: Buffer; text: string }> {
while (true) {
const all = this.buffer()
if (all.length > DOT_LINE.length && all.subarray(all.length - DOT_LINE.length).equals(DOT_LINE)) {
if (this.length > DOT_LINE.length && this.endsWith(DOT_LINE)) {
const all = this.buffer()
const raw = all.subarray(0, all.length - DOT_LINE.length)
try {
const text = unzipSync(raw).toString('utf8')
const inflated = unzipSync(raw)
this.take(all.length)
return { raw: Buffer.from(raw), text }
return { raw: Buffer.from(raw), text: wantText ? inflated.toString('utf8') : '' }
} catch {
// ".\r\n" inside the compressed data: wait for more.
}