Go Benchmark
Error Handling Cost
What creating, wrapping, and inspecting errors really costs.
Almost every Go function returns an error, and most codebases wrap them on the way up with fmt.Errorf("...: %w", err) — but few people know what that convention costs. This benchmark measures the full error lifecycle: creating an error with errors.New, formatting one with fmt.Errorf, wrapping with the %w verb, and checking errors via a direct sentinel comparison, errors.Is, and errors.As. The takeaway: creating and formatting errors allocates on every call, while checking them is nearly free — so the cost lives on the error-producing path, not the error-checking path.
1 CPU
32 CPUs
Compares an existing error against a package-level sentinel with err == errNotFound. A plain interface comparison: no allocation, no unwrapping, effectively free — but it breaks as soon as anyone wraps the error in between.
Errors Is #
Calls errors.Is(err, errNotFound) on a two-level wrapped chain. It walks the chain via Unwrap() and compares each link against the target. Slower than a raw ==, but it is the only comparison that survives wrapping.
Errors New #
Creates a fresh error with errors.New("user not found") on every iteration. Each call allocates a new errorString value on the heap. This is why sentinel errors are declared once at package level instead of being recreated per call.
Errors As #
Calls errors.As(err, &target) on a two-level wrapped chain to extract a custom *NotFoundError. Like errors.Is it walks the chain, but additionally performs a type check per link via reflection, making it the most expensive check.
Fmt Errorf #
Builds an error with fmt.Errorf("loading user %d: %v", i, err). On top of the allocation, this pays for fmt's reflection-based formatting of the verbs. The %v verb flattens the cause into the message without keeping it in the chain.
Same as fmt.Errorf, but uses the %w verb, producing a wrapError that keeps a reference to the cause so errors.Is and errors.As can unwrap it later. This is the idiomatic way to add context while preserving the original error.
Contributors