mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-02 11:15:03 +03:00
perf(wirecodec): decode a config envelope into one buffer
The shared zstd decoder grew its output per frame, copying everything decoded so far for each extra frame, so 30 KB of tiny frames cost about 8 GB of allocation and seconds of CPU per request. The output buffer is now sized once from the first frame's declared size (Compress writes a single frame) with decoding capped at that capacity, and callers waiting for a decoder worker no longer each hold a buffer.
This commit is contained in:
@@ -2,6 +2,7 @@ package wirecodec
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -49,3 +50,17 @@ func TestSha256HexStableAndSensitive(t *testing.T) {
|
||||
t.Fatalf("expected 64 hex chars, got %d", len(a))
|
||||
}
|
||||
}
|
||||
|
||||
// Every extra frame made the decoder copy all output so far into a larger buffer, so a
|
||||
// few KiB of tiny frames cost gigabytes of allocation for one authenticated request.
|
||||
func TestDecompressOfManyFramesAllocatesTheOutputOnce(t *testing.T) {
|
||||
frame := Compress(bytes.Repeat([]byte("A"), 4096))
|
||||
src := bytes.Repeat(frame, 2000)
|
||||
var before, after runtime.MemStats
|
||||
runtime.ReadMemStats(&before)
|
||||
_, _ = Decompress(src, 8<<20)
|
||||
runtime.ReadMemStats(&after)
|
||||
if allocated := after.TotalAlloc - before.TotalAlloc; allocated > 64<<20 {
|
||||
t.Fatalf("decoding %d bytes of frames allocated %d MiB", len(src), allocated>>20)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user