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

Memory improvements to loadRawSpec #634

Merged

Conversation

paulcacheux
Copy link
Contributor

@paulcacheux paulcacheux commented Apr 21, 2022

This PR contains memory usage (and small cpu) improvements to lawRawSpec through:

  • precomputing the amount of required fixups when building the type graph
  • guess-timating the amount of types when reading the btf types reducing the amount of buffer reallocation

Benchmark:

>>> sudo go test -run=XXX -bench=BenchmarkParseVmlinux ./internal/btf

Before (master branch):

goos: linux
goarch: amd64
pkg: github.com/cilium/ebpf/internal/btf
cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
BenchmarkParseVmlinux-4   	       9	 118640220 ns/op	96579569 B/op	  786353 allocs/op
PASS
ok  	github.com/cilium/ebpf/internal/btf	2.049s

After (updated after review):

goos: linux
goarch: amd64
pkg: github.com/cilium/ebpf/internal/btf
cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
BenchmarkParseVmlinux-4   	      14	  76856666 ns/op	53361862 B/op	  574838 allocs/op
PASS
ok  	github.com/cilium/ebpf/internal/btf	2.001s

Happy to discuss future paths of improvements


func unsafeBytesToString(bytes []byte) string {
// trick used by https://go.dev/src/strings/builder.go#L45
return *(*string)(unsafe.Pointer(&bytes))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a personal preference:
I prefer the use of reflect.StringHeader{} over this approach. If bytes contains malicious data and Len in reflect.StringHeader{} is not set, it can result in unintended side effects when using the string.
Both approaches avoid additional allocations so this is an improvement memory wise.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave your suggestion a quick whirl:

func unsafeBytesToString(bytes []byte) string {
	if len(bytes) == 0 {
		return ""
	}

	sh := &reflect.StringHeader{
		Data: uintptr(unsafe.Pointer(&bytes[0])),
		Len:  len(bytes),
	}

	str := *(*string)(unsafe.Pointer(sh))
	runtime.KeepAlive(bytes)
	return str
}

Seems to work, though some linter complains about this being a possible misuse of StringHeader. What do you mean with bytes containing malicious data though?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing I'm trying to figure out: this trick effectively pins the entire string table in memory. So while we allocate less overall, the peak memory usage after parsing might be higher. I'm thinking of a case where a user parses vmlinux, gets out some type they are interested in, and afterwards discards the Spec. The single retained type would lock the string table into memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true sadly, and it may not be acceptable

@lmb lmb self-requested a review April 22, 2022 09:21
@lmb
Copy link
Collaborator

lmb commented Apr 22, 2022

It's cool to see these improvements, thanks a lot! I'll do a full review in a bit, but how about merging the non-unsafe commits? I have an idea how we might be able to cut down allocations without pinning the memory, but it needs a bit of experimenting.

Copy link
Collaborator

@lmb lmb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I have some small remarks. Could you clean up the commit history a bit?

@paulcacheux paulcacheux force-pushed the paulcacheux/inflate-raw-types-improvements branch from 853bf32 to 25ccfbf Compare April 23, 2022 07:14
@lmb lmb force-pushed the paulcacheux/inflate-raw-types-improvements branch from 25ccfbf to de763c3 Compare April 23, 2022 10:40
Copy link
Collaborator

@lmb lmb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@lmb lmb merged commit 31c4e1c into cilium:master Apr 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants