Skip to content

Commit

Permalink
btf: read all line info records in one go, instead of one by one
Browse files Browse the repository at this point in the history
`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 <[email protected]>
  • Loading branch information
paulcacheux committed Jan 24, 2025
1 parent a4a6c9f commit fb809f7
Showing 1 changed file with 10 additions and 12 deletions.
22 changes: 10 additions & 12 deletions btf/ext_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit fb809f7

Please sign in to comment.