From 0f8cdaac5291a178a8eef16d3343e625ce91f275 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Thu, 14 Sep 2023 11:18:03 -0500 Subject: [PATCH] Use zero-copy decoding for reflists Reflists are basically stored as arrays of strings, which are quite space-efficient in MessagePack. Thus, using zero-copy decoding results in nice performance and memory savings, because the overhead of separate allocations ends up far exceeding the overhead of the original slice. With the included benchmark run for 20s with -benchmem, the runtime, memory usage, and allocations go from ~740us/op, ~192KiB/op, and 4100 allocs/op to ~240us/op, ~97KiB/op, and 13 allocs/op, respectively. Signed-off-by: Ryan Gonzalez --- deb/reflist.go | 4 +++- deb/reflist_bench_test.go | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/deb/reflist.go b/deb/reflist.go index 8a795da57..25cb0b6e1 100644 --- a/deb/reflist.go +++ b/deb/reflist.go @@ -71,7 +71,9 @@ func (l *PackageRefList) Encode() []byte { // Decode decodes msgpack representation into PackageRefLit func (l *PackageRefList) Decode(input []byte) error { - decoder := codec.NewDecoderBytes(input, &codec.MsgpackHandle{}) + handle := &codec.MsgpackHandle{} + handle.ZeroCopy = true + decoder := codec.NewDecoderBytes(input, handle) return decoder.Decode(l) } diff --git a/deb/reflist_bench_test.go b/deb/reflist_bench_test.go index 367f3d098..b377574ce 100644 --- a/deb/reflist_bench_test.go +++ b/deb/reflist_bench_test.go @@ -28,3 +28,20 @@ func BenchmarkReflistSimpleMerge(b *testing.B) { l.Merge(r, false, true) } } + +func BenchmarkReflistDecode(b *testing.B) { + const count = 4096 + + r := NewPackageRefList() + for i := 0; i < count; i++ { + r.Refs = append(r.Refs, []byte(fmt.Sprintf("Pamd64 pkg%d %d", i, i))) + } + + sort.Sort(r) + data := r.Encode() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + (&PackageRefList{}).Decode(data) + } +}