From fb809f757e78337e0f308af6cc5e52dd5784b638 Mon Sep 17 00:00:00 2001 From: Paul Cacheux Date: Fri, 24 Jan 2025 17:28:59 +0100 Subject: [PATCH] btf: read all line info records in one go, instead of one by one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `binary.Read` is able to directly read its result in a slice, and this is way more efficient from a CPU and memory allocation standpoint │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ ParseLineInfoRecords-10 288.6µ ± 3% 141.3µ ± 4% -51.02% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ ParseLineInfoRecords-10 128.0Ki ± 0% 128.0Ki ± 0% ~ (p=1.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ ParseLineInfoRecords-10 4098.000 ± 0% 3.000 ± 0% -99.93% (p=0.000 n=10) Signed-off-by: Paul Cacheux --- btf/ext_info.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/btf/ext_info.go b/btf/ext_info.go index 2c684fe2a..deb058bf0 100644 --- a/btf/ext_info.go +++ b/btf/ext_info.go @@ -667,29 +667,27 @@ func parseLineInfos(r io.Reader, bo binary.ByteOrder, strings *stringTable) (map // sub-section of .BTF.ext. func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, recordNum uint32, offsetInBytes bool) ([]bpfLineInfo, error) { var li bpfLineInfo - if exp, got := uint32(binary.Size(li)), recordSize; exp != got { // BTF blob's record size is longer than we know how to parse. return nil, fmt.Errorf("expected LineInfo record size %d, but BTF blob contains %d", exp, got) } - out := make([]bpfLineInfo, 0, recordNum) - for i := uint32(0); i < recordNum; i++ { - if err := binary.Read(r, bo, &li); err != nil { - return nil, fmt.Errorf("can't read line info: %v", err) - } + out := make([]bpfLineInfo, recordNum) + if err := binary.Read(r, bo, out); err != nil { + return nil, fmt.Errorf("can't read line info: %v", err) + } - if offsetInBytes { - if li.InsnOff%asm.InstructionSize != 0 { - return nil, fmt.Errorf("offset %v is not aligned with instruction size", li.InsnOff) + if offsetInBytes { + for i := range out { + current := &out[i] + if current.InsnOff%asm.InstructionSize != 0 { + return nil, fmt.Errorf("offset %v is not aligned with instruction size", current.InsnOff) } // ELF tracks offset in bytes, the kernel expects raw BPF instructions. // Convert as early as possible. - li.InsnOff /= asm.InstructionSize + current.InsnOff /= asm.InstructionSize } - - out = append(out, li) } return out, nil