-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
runtime: mid-stack inlining vs. FuncForPC #29582
Comments
Change https://golang.org/cl/156364 mentions this issue: |
If this is to be included in 1.12, we need a decision ASAP. |
I would like to get it in for 1.12 if it is clean and @randall77 agrees. |
One more tweak is needed to make |
Change https://golang.org/cl/156657 mentions this issue: |
In 1.11 we stored "return addresses" in the result of runtime.Callers. I changed that behavior in CL 152537 to store an address in the call instruction itself. This CL reverts that part of 152537. The change in 152537 was made because we now store pcs of inline marks in the result of runtime.Callers as well. This CL will now store the address of the inline mark + 1 in the results of runtime.Callers, so that the subsequent -1 done in CallersFrames will pick out the correct inline mark instruction. This CL means that the results of runtime.Callers can be passed to runtime.FuncForPC as they were before. There are a bunch of packages in the wild that take the results of runtime.Callers, subtract 1, and then call FuncForPC. This CL keeps that pattern working as it did in 1.11. The changes to runtime/pprof in this CL are exactly a revert of the changes to that package in 152537 (except the locForPC comment). Update #29582 Change-Id: I04d232000fb482f0f0ff6277f8d7b9c72e97eb48 Reviewed-on: https://go-review.googlesource.com/c/156657 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
Fixes cockroachdb#17770. This commit fixes the last user of `runtime.Callers` that misused the stdlib function by translating the PC values it returned directly into symbolic information (see https://golang.org/pkg/runtime/#Callers). Go's documentation warns that this is a recipe for disaster when mixed with mid-stack inlining. The other concern in cockroachdb#17770 was this comment: cockroachdb#17770 (comment). This was discussed in golang/go#29582 and addressed in golang/go@956879d. An alternative would be to use `runtime.Caller` here, but that would force an allocation that was hard-earned in cockroachdb#29017. Instead, this commit avoids any performance hit. ``` name old time/op new time/op delta Header-4 267ns ± 1% 268ns ± 0% ~ (p=0.584 n=10+10) VDepthWithVModule-4 260ns ± 3% 255ns ± 1% -1.87% (p=0.018 n=10+9) name old alloc/op new alloc/op delta Header-4 0.00B 0.00B ~ (all equal) VDepthWithVModule-4 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Header-4 0.00 0.00 ~ (all equal) VDepthWithVModule-4 0.00 0.00 ~ (all equal) ``` Release note: None
35014: kv: introduce new "max outstanding size" setting to txnPipeliner r=nvanbenschoten a=nvanbenschoten Fixes #32522. This change creates a new cluster setting called: ``` kv.transaction.write_pipelining_max_outstanding_size ``` It limits the size in bytes that can be dedicated to tracking in-flight writes that have been pipelined. Once this limit is hit, not more writes will be pipelined by a transaction until some of the writes are proven and removed from the outstanding write set. This change once again illustrates the need for periodic proving of outstanding writes. We touch upon that in the type definition's comment and in #35009. Release note: None 35199: log: fix remaining misuse of runtime.Callers/runtime.FuncForPC r=nvanbenschoten a=nvanbenschoten Fixes #17770. This commit fixes the last user of `runtime.Callers` that misused the stdlib function by translating the PC values it returned directly into symbolic information (see https://golang.org/pkg/runtime/#Callers) [1]. Go's documentation warns that this is a recipe for disaster when mixed with mid-stack inlining. The other concern in #17770 was this comment: #17770 (comment). This was discussed in golang/go#29582 and addressed in golang/go@956879d. An alternative would be to use `runtime.Caller` here, but that would force an allocation that was hard-earned in #29017. Instead, this commit avoids any performance hit. ``` name old time/op new time/op delta Header-4 267ns ± 1% 268ns ± 0% ~ (p=0.584 n=10+10) VDepthWithVModule-4 260ns ± 3% 255ns ± 1% -1.87% (p=0.018 n=10+9) name old alloc/op new alloc/op delta Header-4 0.00B 0.00B ~ (all equal) VDepthWithVModule-4 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Header-4 0.00 0.00 ~ (all equal) VDepthWithVModule-4 0.00 0.00 ~ (all equal) ``` [1] I went through and verified that this was still correct. Release note: None 35203: closedts: react faster to config changes r=danhhz a=tbg This approximately halves the duration of `make test PKG=./pkg/ccl/changefeedccl TESTS=/sinkless`, from ~60s to ~30s. Touches #34455. Release note: None Co-authored-by: Nathan VanBenschoten <[email protected]> Co-authored-by: Tobias Schottdorf <[email protected]>
I've seen lots of instances of code like this:
(e.g. https://github.com/stretchr/testify/blob/ffdc059bfe9ce6a4e144ba849dbedead332c6053/mock/mock.go#L317)
This code won't work as expected when mid-stack inlining is enabled. If we have
Then 1.12 prints
main.main
, notmain.f
as would be printed for 1.11.This is because
FuncForPC
is specified as follows:The pc returned by
runtime.Caller
is inmain.main
on an instruction from the body ofmain.f
. Because of the spec worded as above, we getmain.main
as a result.The current "fix" for this is to require everyone to move to using
runtime.CallersFrames
(see footnote 1) which handles inlined frames correctly. This is the long term solution, but requires users ofruntime.Caller{,s}
+runtime.FuncForPC
to do something active to keep their code working for 1.12.I propose instead to change how
FuncForPC
works so the above code does not need a fix. If we instead use this spec:(outermost -> innermost, plus some weasel words for what Entry() returns for an inlined function.)
This will fix the above code transparently. There are 2 wrinkles to this otherwise elegant solution:
Func
to return fromFuncForPC
for inlined functions.I don't think number 1 is a huge problem. The only pcs that are exposed by the runtime are those returned by
runtime.Caller{,s}
. Most inlinings we do in 1.11 are leaf inlinings, whichruntime.Caller{,s}
can't observe. We also inline functions which callpanic
. Thoseruntime.Caller{,s}
can observe, but would have to be called from within a deferred handler, which seems rare (and is ugly anyway because things likeruntime.gopanic
are on the stack).Of course, someone could get a pc by other means, using
unsafe
, a profiling library, or who knows where else. Those users might see something unexpected.I have a CL which will solve number 2.
FuncForPC
has enough information to construct aFunc
dynamically for the inlined body. It meansFuncForPC
might allocate, but otherwise it's not observable by the user (other than the weird "what does Entry() return" problem mentioned above).footnote 1: The
testify
package fixed this problem by introducing//go:noinline
directives. That doesn't seem to be a good approach in general.The text was updated successfully, but these errors were encountered: