Skip to content

Instantly share code, notes, and snippets.

@zachmu
Last active June 4, 2024 06:30
Show Gist options
  • Save zachmu/00d0410431f9d8d314155361836eecdd to your computer and use it in GitHub Desktop.
Save zachmu/00d0410431f9d8d314155361836eecdd to your computer and use it in GitHub Desktop.
Go error handling benchmark
// Copyright 2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"errors"
"fmt"
"testing"
)
var notFoundErr = errors.New("not found")
type resultType struct {}
type boolStore struct {}
//go:noinline
func (b *boolStore) GetValue(found bool) (*resultType, bool, error) {
if found {
return &resultType{}, true, nil
} else {
return nil, false, nil
}
}
type errStore struct {}
//go:noinline
func (b *errStore) GetValue(found bool) (*resultType, error) {
if found {
return &resultType{}, nil
} else {
return nil, notFoundErr
}
}
type panicStore struct{}
//go:noinline
func (b *panicStore) GetValue(found bool) *resultType {
if found {
return &resultType{}
} else {
panic(notFoundErr)
}
}
type wrappedErrStore struct{}
//go:noinline
func (b *wrappedErrStore) GetValue(found bool) (*resultType, error) {
result, err := b.queryValueStore(found)
if err != nil {
return nil, fmt.Errorf("GetValue couldn't get a value: %w", err)
}
return result, nil
}
//go:noinline
func (b *wrappedErrStore) queryValueStore(found bool) (*resultType, error) {
result, err := b.queryDisk(found)
if err != nil {
return nil, fmt.Errorf("queryValueStore couldn't get a value: %w", err)
}
return result, nil
}
//go:noinline
func (b *wrappedErrStore) queryDisk(found bool) (*resultType, error) {
result, err := b.readValueFromDiskFake(found)
if err != nil {
return nil, fmt.Errorf("queryDisk couldn't get a value: %w", err)
}
return result, nil
}
//go:noinline
func (b *wrappedErrStore) readValueFromDiskFake(found bool) (*resultType, error) {
if found {
return &resultType{}, nil
} else {
return nil, notFoundErr
}
}
type wrappedBoolStore struct {}
//go:noinline
func (b *wrappedBoolStore) GetValue(found bool) (*resultType, bool, error) {
result, found, err := b.queryValueStore(found)
if err != nil {
return nil, false, fmt.Errorf("GetValue couldn't get a value: %w", err)
}
return result, found, nil
}
//go:noinline
func (b *wrappedBoolStore) queryValueStore(found bool) (*resultType, bool, error) {
result, found, err := b.queryDisk(found)
if err != nil {
return nil, false, fmt.Errorf("queryValueStore couldn't get a value: %w", err)
}
return result, found, nil
}
//go:noinline
func (b *wrappedBoolStore) queryDisk(found bool) (*resultType, bool, error) {
result, found, err := b.readValueFromDiskFake(found)
if err != nil {
return nil, false, fmt.Errorf("queryDisk couldn't get a value: %w", err)
}
return result, found, nil
}
//go:noinline
func (b *wrappedBoolStore) readValueFromDiskFake(found bool) (*resultType, bool, error) {
if found {
return &resultType{}, true, nil
} else {
return nil, false, nil
}
}
func BenchmarkNotFoundBool(b *testing.B) {
var bs boolStore
for i := 0; i < b.N; i++ {
val, found, err := bs.GetValue(i < 0)
if err != nil {
b.Fatal(err)
} else if found {
b.Fatal("expected not found")
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundErrorsIs(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if errors.Is(err, notFoundErr) {
// nothing to do
} else if err != nil {
b.Fatal(err)
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundErrorsIsNilCheck(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if err != nil {
if errors.Is(err, notFoundErr) {
// nothing to do
} else {
b.Fatal(err)
}
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundErrEqual(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if err == notFoundErr {
// nothing to do
} else if err != nil {
b.Fatal(err)
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundErrEqualNilCheck(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if err != nil {
if err == notFoundErr {
// nothing to do
} else {
b.Fatal(err)
}
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundWrappedErr(b *testing.B) {
var es wrappedErrStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if errors.Is(err, notFoundErr) {
// nothing to do
} else if err != nil {
b.Fatal(err)
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundWrappedErrNilCheck(b *testing.B) {
var es wrappedErrStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i < 0)
if err != nil {
if errors.Is(err, notFoundErr) {
// nothing to do
} else {
b.Fatal(err)
}
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundWrappedBool(b *testing.B) {
var bs wrappedBoolStore
for i := 0; i < b.N; i++ {
val, found, err := bs.GetValue(i < 0)
if err != nil {
b.Fatal(err)
} else if found {
b.Fatal("expected not found")
}
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkNotFoundPanic(b *testing.B) {
var es panicStore
for i := 0; i < b.N; i++ {
var val *resultType
func() {
defer func() {
// recover panic
err := recover()
if err == nil {
b.Fatal("expected panic")
}
}()
val = es.GetValue(i < 0)
}()
if val != nil {
b.Fatal("expected nil")
}
}
}
func BenchmarkFoundBool(b *testing.B) {
var bs boolStore
for i := 0; i < b.N; i++ {
val, found, err := bs.GetValue(i >= 0)
if err != nil {
b.Fatal(err)
} else if !found {
b.Fatal("expected found")
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundErrorsIs(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if errors.Is(err, notFoundErr) {
b.Fatal("expected found")
} else if err != nil {
b.Fatal(err)
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundErrorsIsNilCheck(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if err != nil {
if errors.Is(err, notFoundErr) {
b.Fatal("expected found")
} else {
b.Fatal(err)
}
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundErrEqual(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if err == notFoundErr {
b.Fatal("expected found")
} else if err != nil {
b.Fatal(err)
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundErrEqualNilCheck(b *testing.B) {
var es errStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if err != nil {
if err == notFoundErr {
b.Fatal("expected found")
} else {
b.Fatal(err)
}
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundWrappedErr(b *testing.B) {
var es wrappedErrStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if errors.Is(err, notFoundErr) {
b.Fatal(err)
} else if err != nil {
b.Fatal(err)
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundWrappedErrNilCheck(b *testing.B) {
var es wrappedErrStore
for i := 0; i < b.N; i++ {
val, err := es.GetValue(i >= 0)
if err != nil {
if errors.Is(err, notFoundErr) {
b.Fatal(err)
} else {
// nothing to do
}
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundWrappedBool(b *testing.B) {
var bs wrappedBoolStore
for i := 0; i < b.N; i++ {
val, found, err := bs.GetValue(i >= 0)
if err != nil {
b.Fatal(err)
} else if !found {
b.Fatal("expected found")
}
if val == nil {
b.Fatal("expected not nil")
}
}
}
func BenchmarkFoundPanic(b *testing.B) {
var es panicStore
for i := 0; i < b.N; i++ {
var val *resultType
func() {
defer func() {
// recover panic
err := recover()
if err != nil {
b.Fatal("unexpected panic")
}
}()
val = es.GetValue(i >= 0)
}()
if val == nil {
b.Fatal("expected not nil")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment