Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
1 of 2 tasks
lmb opened this issue Jun 14, 2023 · 3 comments
Open
1 of 2 tasks

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

lmb opened this issue Jun 14, 2023 · 3 comments
Labels
enhancement New feature or request

Comments

@lmb
Copy link
Collaborator

lmb commented Jun 14, 2023

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: #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.

  • Pointer to or slice of valid types (otherwise we can't get unsafe.Pointer to it)
  • Primitive types like uint64
  • Arrays of valid types
  • Structs of valid types which have no compiler inserted padding, aka packed structs

Tasks

@lmb lmb added the enhancement New feature or request label Jun 14, 2023
@lmb lmb self-assigned this Jun 14, 2023
@brycekahle
Copy link
Contributor

  • Structs of valid types which have no compiler inserted padding, aka packed structs

Why is the no padding required?

@lmb
Copy link
Collaborator Author

lmb commented Jun 14, 2023

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
Copy link
Contributor

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

@lmb lmb removed their assignment Oct 11, 2023
@lmb lmb assigned lmb and unassigned lmb Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants