]> git.feebdaed.xyz Git - 0xmirror/ebpf.git/commit
map: zero-allocation operations for common types
authorLorenz Bauer <lmb@isovalent.com>
Thu, 14 Sep 2023 14:04:09 +0000 (15:04 +0100)
committerTimo Beckers <ti-mo@users.noreply.github.com>
Thu, 14 Sep 2023 15:45:38 +0000 (17:45 +0200)
commit4609dc73fa846184b379ae1ee771cc9e95e2ecbc
tree4609f3868a7eff36a658d732bbbadb96d4ed72f4
parent74e1d7bed434f93a7a8baaa76526fc1a6d594d51
map: zero-allocation operations for common types

Map keys and values are currently marshaled into []byte by souped
up versions of binary.Write and binary.Read. This allows users to
be blissfully unaware of compiler inserted padding on the Go side.
This is wasteful in case the Go in-memory representation matches
what the kernel expects because we need additional allocations.

Refactor syscall marshaling into a new package sysenc which
encapsulates the logic we need to determine whether a Go type
is safe for zero-allocation / zero-copy marshaling. The type
must be a pointer to or a slice of:

* A primitive type like uint32, ... or
* An array of valid types or
* A struct made up of valid types without any compiler
  inserted padding between fields

Per-CPU maps don't support zero-allocation operations for now,
but the new code already makes things a little bit cheaper.

Structs with trailing padding also don't benefit from the
optimization for now. Consider

    type padded struct { A uint32; B uint16 }

Allowing such a type creates an edge case: make([]padding, 1)
uses zero-allocation marshaling while make([]padding, 2)
doesn't, due to interior padding. It's simpler to skip such
types for now.

    goos: linux
    goarch: amd64
    pkg: github.com/cilium/ebpf
    cpu: 12th Gen Intel(R) Core(TM) i7-1260P
                                         │ unsafe.txt  │
                                         │   sec/op    │
    Marshaling/ValueUnmarshalReflect-16    356.1n ± 2%
    Marshaling/KeyMarshalReflect-16        368.6n ± 1%
    Marshaling/ValueBinaryUnmarshaler-16   378.6n ± 2%
    Marshaling/KeyBinaryMarshaler-16       356.2n ± 1%
    Marshaling/KeyValueUnsafe-16           328.0n ± 2%
    PerCPUMarshalling/reflection-16        1.232µ ± 1%

                                         │  unsafe.txt  │
                                         │     B/op     │
    Marshaling/ValueUnmarshalReflect-16    0.000 ± 0%
    Marshaling/KeyMarshalReflect-16        0.000 ± 0%
    Marshaling/ValueBinaryUnmarshaler-16   24.00 ± 0%
    Marshaling/KeyBinaryMarshaler-16       8.000 ± 0%
    Marshaling/KeyValueUnsafe-16           0.000 ± 0%
    PerCPUMarshalling/reflection-16        280.0 ± 0%

                                         │  unsafe.txt  │
                                         │  allocs/op   │
    Marshaling/ValueUnmarshalReflect-16    0.000 ± 0%
    Marshaling/KeyMarshalReflect-16        0.000 ± 0%
    Marshaling/ValueBinaryUnmarshaler-16   1.000 ± 0%
    Marshaling/KeyBinaryMarshaler-16       1.000 ± 0%
    Marshaling/KeyValueUnsafe-16           0.000 ± 0%
    PerCPUMarshalling/reflection-16        3.000 ± 0%

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
15 files changed:
collection.go
internal/endian_be.go
internal/endian_le.go
internal/sysenc/buffer.go [new file with mode: 0644]
internal/sysenc/buffer_test.go [new file with mode: 0644]
internal/sysenc/doc.go [new file with mode: 0644]
internal/sysenc/layout.go [new file with mode: 0644]
internal/sysenc/layout_test.go [new file with mode: 0644]
internal/sysenc/marshal.go [new file with mode: 0644]
internal/sysenc/marshal_test.go [new file with mode: 0644]
map.go
marshalers.go
prog.go
prog_test.go
syscalls.go