Conversation
This is a benchmark created by @rafi. It demonstrates `errors.Is` is very inefficient when the reference error does not match the input error.
Previously, `errors.Is` was very inefficient if the reference error did not match any errors in the chain. There were two significant sources of inefficiency: 1. The code would pessimistically construct the error mark for every error in the input error chain. This is O(chain_length^2). This was a lot of unnecessary allocations and caused the runtime to be O(n^2) in the average case instead of O(n). 2. The code compared the `Error()` message before comparing the types. It is possible to compare error types with zero allocations whereas computing the message often requires an allocation.
3ff6ee5 to
3a21e3d
Compare
| if m1.msg != m2.msg { | ||
| return false | ||
| } | ||
| if len(m1.types) != len(m2.types) { |
There was a problem hiding this comment.
This is a bug that is pretty unlikely to occur in the original implementation that checks error message before types, but its somewhat likely now that we check the types first.
| return true | ||
| } | ||
| for _, reference := range references { | ||
| if Is(err, reference) { |
There was a problem hiding this comment.
I think the reason we didn't use this implementation originally is Is was pretty slow. So it was better to use the quick check before the slow mark check. Now that Is is efficient, we don't need to duplicate the implementations.
There was a problem hiding this comment.
Thanks for the consolidation.
|
dhartunian
left a comment
There was a problem hiding this comment.
@dhartunian reviewed 1 of 3 files at r1, all commit messages.
Reviewable status: 1 of 3 files reviewed, 2 unresolved discussions (waiting on @jeffswenson)
| return true | ||
| } | ||
| for _, reference := range references { | ||
| if Is(err, reference) { |
There was a problem hiding this comment.
Thanks for the consolidation.
|
Thanks for the review! |
Update the errors package to get the performance optimization from cockroachdb/errors#153. Release note: none Informs: cockroachdb#154125
Update the errors package to get the performance optimization from cockroachdb/errors#153. Release note: none Informs: cockroachdb#154125
155254: go.mod: update cockroachdb/errors package r=jeffswenson a=jeffswenson Update the errors package to get the performance optimization from cockroachdb/errors#153. Release note: none Informs: #154125 Co-authored-by: Jeff Swenson <jeffswenson@betterthannull.com>
Update the errors package to get the performance optimization from cockroachdb/errors#153. Release note: none Informs: cockroachdb#154125
benchmark: add a benchmark for the errors package
This is a benchmark created by @rafiss. It demonstrates
errors.Isis very inefficient when the reference error does not match the
input error.
errbase: optimize errors.Is
Previously,
errors.Iswas very inefficient if the reference error didnot match any errors in the chain.
There were two significant sources of inefficiency:
error in the input error chain. This is O(chain_length^2). This was
a lot of unnecessary allocations and caused the runtime to be O(n^2)
in the average case instead of O(n).
Error()message before comparing the types.It is possible to compare error types with zero allocations whereas
computing the message often requires an allocation.
refs: cockroachdb/cockroach#154555
This change is