-
Notifications
You must be signed in to change notification settings - Fork 721
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
Memory improvements to loadRawSpec
#634
Conversation
internal/btf/strings.go
Outdated
|
||
func unsafeBytesToString(bytes []byte) string { | ||
// trick used by https://go.dev/src/strings/builder.go#L45 | ||
return *(*string)(unsafe.Pointer(&bytes)) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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. |
There was a problem hiding this 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?
853bf32
to
25ccfbf
Compare
25ccfbf
to
de763c3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
This PR contains memory usage (and small cpu) improvements to
lawRawSpec
through:Benchmark:
Before (master branch):
After (updated after review):
Happy to discuss future paths of improvements