-
Notifications
You must be signed in to change notification settings - Fork 26
Faster C.Run by using less reflect #160
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
Conversation
7295bd0 to
3482a30
Compare
|
@frankban Rebased. This important optimization (with my other fixes) are worth a release. |
|
ping @frankban |
|
This looks very interesting. We are discussing with @rogpeppe about other possible ways for introducing this optimization. Thanks for this work! |
|
I could go further and completely remove the An alternate implementation would use generics to enforce the signature at compile time. But are you ready to push the minimum Go version required from 1.13 to 1.18? |
|
Well, Go doesn't have generic methods yet, so I don't see how a compile-time check of the subtest signature could be enforced. |
Extract signature check of the Run method. This will allow to cache the result in future commits.
Add a dummy implementation getRunFuncSignature (it will be replaced by concrete implementation in future commits) called getRunFuncSignature. Add a benchmark that allows to compare the performance of getRunFuncSignatureCache with getRunFuncSignature. Of course the results are currently useless.
This will give a real boost to C.Run by removing most uses of reflect on each Run. Benchmark results: go test -bench BenchmarkCRunGetFuncSig -benchmem BenchmarkCRunGetFuncSig/*testing.T-no-cache-4 562579 2142 ns/op 168 B/op 4 allocs/op BenchmarkCRunGetFuncSig/*testing.T-with-cache-4 183638598 7.514 ns/op 0 B/op 0 allocs/op BenchmarkCRunGetFuncSig/*testing.B-no-cache-4 608715 2626 ns/op 168 B/op 4 allocs/op BenchmarkCRunGetFuncSig/*testing.B-with-cache-4 100000000 11.00 ns/op 0 B/op 0 allocs/op BenchmarkCRunGetFuncSig/*quicktest.C-no-cache-4 636226 2523 ns/op 168 B/op 4 allocs/op BenchmarkCRunGetFuncSig/*quicktest.C-with-cache-4 68991796 48.91 ns/op 0 B/op 0 allocs/op
|
Rebased on top of v1.14.6. |
|
Replaced by #165 which completely bypass |
This is an alternative to PRs frankban#160 and frankban#165. It's essentially the same as PR frankban#165 except that it uses generics to reduce the amount of duplicated code. Instead of just amortizing the checking of the type, when the argument type of the function passed to `Run` is known, it bypasses the reflect-based code altogether. We don't bother implementing the optimization on pre-generics Go versions because those are end-of-lifetime anyway. I've added an implementation-independent benchmark. ``` goos: linux goarch: amd64 pkg: github.com/frankban/quicktest cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz │ base │ thisPR │ │ sec/op │ sec/op vs base │ CNewAndRunWithCustomType-8 1077.5n ± 5% 136.8n ± 6% -87.30% (p=0.002 n=6) CRunWithCustomType-8 1035.00n ± 11% 66.43n ± 3% -93.58% (p=0.002 n=6) geomean 1.056µ 95.33n -90.97% ```
This is an alternative to PRs frankban#160 and frankban#165. It's essentially the same as PR frankban#165 except that it uses generics to reduce the amount of duplicated code. Instead of just amortizing the checking of the type, when the argument type of the function passed to `Run` is known, it bypasses the reflect-based code altogether. We don't bother implementing the optimization on pre-generics Go versions because those are end-of-lifetime anyway. I've added an implementation-independent benchmark. ``` goos: linux goarch: amd64 pkg: github.com/frankban/quicktest cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz │ base │ thisPR │ │ sec/op │ sec/op vs base │ CNewAndRunWithCustomType-8 1077.5n ± 5% 136.8n ± 6% -87.30% (p=0.002 n=6) CRunWithCustomType-8 1035.00n ± 11% 66.43n ± 3% -93.58% (p=0.002 n=6) geomean 1.056µ 95.33n -90.97% ```
In
C.Runbypass check of the signature of theRunmethod ofc.TBby using a prefilled table for the common cases of*testing.T,*testing.Band*quicktest.C.This serie of patches shows the developement process:
getRunFuncSignaturegetRunFuncSignaturegetRunFuncSignatureand add aBenchmarkCRunGetFuncSigto compare themgetRunFuncSignatureCache(see commit for results)getRunFuncSignatureCacheinstead ofgetRunFuncSignatureinC.Run