-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Lazily render mock diff output on successful match #1615
base: master
Are you sure you want to change the base?
Lazily render mock diff output on successful match #1615
Conversation
* Stop querying for stack frames multiple times on CallerInfo() * fix * refill stack frame buffer after it's exhausted * cleanup
This includes the CallerInfo change from #1614 |
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've considered and tried a similar approach before when trying to address #1597. It only removes the race from passing tests, though. If it comes with a sizable performance benefit I'm more than happy to lazily render these.
I'd like it to be separated from #1614, they're not dependant on one another, right?
Then there's some changes I'd like around the use of outputRenderers
. I'm fairly sure the slice isn't even necessary, you can change actualFmt
's type from string
to func() string
and change all its references to actualFmt()
.
if !more { | ||
// We know we already have less than a buffer's worth of frames | ||
if !maybeMore { | ||
break | ||
} | ||
offset += stackFrameBufferSize | ||
n = runtime.Callers(offset, pcs) | ||
if n == 0 { | ||
break | ||
} | ||
|
||
maybeMore = n == stackFrameBufferSize | ||
|
||
frames = runtime.CallersFrames(pcs[:n]) | ||
} |
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'm not a fan of more
and maybeMore
, this code is actually two nested loops and I think it would be more readable if you coded it that way. I think that pure behaviour is usually better than data (varibles) used only to alter behaviour.
This code is also from #1614, it might be quicker to review this change if you keep the two PRs separate.
var differences int | ||
|
||
maxArgCount := len(args) | ||
if len(objects) > maxArgCount { | ||
maxArgCount = len(objects) | ||
} | ||
|
||
for i := 0; i < maxArgCount; i++ { | ||
outputRenderers := []outputRenderer{} |
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.
interface{} says nothing, the case for this being type string
isn't actually necessary, you can just use a static function. Then you no longer need the unreachable panic.
outputRenderers := []outputRenderer{} | |
outputRenderers := []func() string |
I honestly don't remember if they are or are not given how long it's been since I wrote this. I can try to take a pass on cleaning this and the other PR up after next week (short week for thanksgiving in the states) |
Summary
Sprintf
-ing theactual
value can be costly. Switch successful matches to use thunks to lazily render their output, and fully avoid rendering their output when there are no differences since we return a constant string in that case anywaysChanges
Motivation
<Whatever>Request
structs that are costly to%v
viaSprintf
.Sprintf
showed up as a tangible contributor to runtime performance when profiling some of our heavier tests. The below ~5s cpu time spent onSprintf
goes away completely here in one of our exemplar testsRelated issues