-
Notifications
You must be signed in to change notification settings - Fork 34
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
Add TraceFrom(pcs) for "on-demand" StackTrace instantiation #25
base: develop
Are you sure you want to change the base?
Conversation
Allows to record just the pcs from runtime.Callers when an error occurs and convert them to a StackTrace only if the trace is actually needed, e.g. when printing to a log. Improves performance about 4x.
This is an interesting idea. I would like to think about this a bit before deciding to merge it. In the mean time, would you kindly target this PR to the |
Re-targeted to |
Thanks for retargeting. I've taken a closer look at this PR and run the benchmarks. I'm persuaded that this would be a valuable addition, but I see some things we should improve before merging. I'll try post full review comments before the end of the week. |
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 for the PR. Please make the changes I've suggested below.
@@ -208,14 +208,24 @@ func (cs CallStack) Format(s fmt.State, verb rune) { | |||
s.Write(closeBracketBytes) | |||
} | |||
|
|||
// Convenience wrapper around runtime.Callers() | |||
func Callers(skip int) []uintptr { |
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 think we should choose a function name that aligns more closely to the Trace
function since they both serve the same purpose just at different levels of abstraction. We should also improve the doc comment while we're at it.
Consider:
// TraceFast returns a low level representation of a CallStack. Use TraceFrom
// to convert the result into a CallStack. Use TraceFast as a lighter alternative
// to Trace when you want to record stack trace but will not always format it.
func TraceFast() []uintptr { ... }
cs := make(CallStack, 0, n) | ||
// TraceFrom creates a CallStack from the given program counters (as generated | ||
// by runtime.Callers) | ||
func TraceFrom(pcs []uintptr) CallStack { |
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.
The docs for TraceFrom should make it clear that it should only be given a return value from TraceFast
and not just any slice of pcs. That gives us some wiggle room to adjust the implemenation without having to be compatible with arbitrary pcs []uintptr
values.
} | ||
|
||
func BenchmarkCallers50(b *testing.B) { | ||
b.StopTimer() |
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.
We should call b.StopTimer
inside the loop before calling deepCallers
like it is in BenchmarkCallers10
. I realize you followed the pattern I had in the BenchmarkTrace functions but I did it wrong there and never noticed until now. Please fix those too if you don't mind.
@lukseven We may be able to get the performance gains you want without adding new functions to the API. This package used to be more efficient prior to the introduction of It would be great if we can get the lower upfront cost you want in the existing Let me know if you want to make an attempt at that. |
Allows to record just the pcs from runtime.Callers when an error
occurs and convert them to a StackTrace only if the trace is actually
needed, e.g. when printing to a log.
Improves performance about 4x.