cilium / ebpf

ebpf-go is a pure-Go library to read, modify and load eBPF programs and attach them to various hooks in the Linux kernel.
https://ebpf-go.dev
MIT License
6.31k stars 697 forks source link

map: reduce allocations when (un)marshaling keys and values #1061

Open lmb opened 1 year ago

lmb commented 1 year ago

Timo is in the process of moving cilium/cilium over to use ebpf.Map more consistently and he found that map operations in the lib allocate a lot more than the old code paths. Timo was able to improve that quite a bit with a simple fix: https://github.com/cilium/ebpf/pull/1053 However we are still a bit more inefficient than the previous code.

The reason is that cilium/cilium essentially passes unsafe.Pointer to map keys and values, skipping marshaling altogether. This works since the Go in-memory layout of certain types are identical to the result produced by binary.Write(NativeEndian). There is a check in CI which ensures that types passed as map keys and values have the correct layout (I think?).

I want to investigate if we can extend this approach to all users of the library, without requiring a build time / CI check. The lib should check at run time whether the type of a value satisfies the following invariants and pass unsafe.Pointer to the backing memory of the value.

### Tasks
- [x] Make regular map operations faster
- [ ] Make per-CPU map operations faster
brycekahle commented 1 year ago
  • Structs of valid types which have no compiler inserted padding, aka packed structs

Why is the no padding required?

lmb commented 1 year ago

Because the padding is completely invisible to regular Go. Pretty printing a value doesn't show such padding. What happens when we write into the padding via unsafe? Is padding taken into account when comparing values?

The only way I'd be comfortable with this is if we zeroed the padding somehow, but then we wouldn't do that in the fastpath.

brycekahle commented 1 year ago

Ah, we generate Go types using go tool cgo -godefs which includes the padding. So it sounds like that would still work.