次なる pkg/errors を探してを読んで
https://tech.kanmu.co.jp/entry/2023/06/19/150000 を読んで思ったこと、調べたことを書きます。
pkg/errors の移行先を探すという話で
の2つが候補から最終的には cockroachdb/errors を選んでいました。
検討の中で求めるものの1つとして 性能が大きく劣化しないこと
があげられていてベンチマークが行われていました。
ベンチマークのソースコードと結果は以下になります。
結果 cockroachdb/errors は goark/errs と比較してパフォーマンスは悪いというものでした。
ここで気になるのが何故パフォーマンスが悪いのかというところです。 ベンチマークを公開する上で数値のみだけではなく何故その結果になったのかという分析も付加されていたほうが良いと言うのが僕の考えです。
追試・検証
実際に上記のベンチマークを手元の環境で実行したところ傾向としては同じでした。
cockroachdb/errors
まずは cockroachdb/errors の flamegraph を見てみます。
cockroachdb/errors では StackTrace の Format が重い事がわかります。 そもそも StackTrace は pkg/errors のものを使用しています。
https://github.com/pkg/errors/blob/5dd12d0cfe7f152f80558d591504ce685299311e/stack.go#L64
Frame.Format はあまり最適化されておらず %+v
を使うと Frame ごとに3回 FuncForPC, 2回 FileLine が呼び出されてしまいます。
StackTrace の Format 以外にも strings.ReplaceAll も気になります。 cockroachdb/errors は個人情報を出力しないようにする仕組みが存在しておりその処理で strings.ReplaceAll が使われています。
個人情報を出力しない仕組みの詳細については
を確認してください。
goark/errs
次は goark/errs の flamegraph を見てみます。
まず cockroachdb/errors の方にあった FuncForPC などの関数がありません。 ソースコードを確認したところ出力時に解決するのではなく New したタイミングで解決するようになっています。 しかも New を呼び出した関数名のみを取得します。なので goark/errs は適切にエラーを Wrap しなければスタックトレースになりません。
出力の処理は json.Marshal と fmt.Sprintf を使っています。 json.Marshal を高速化するために goccy/go-json に変えるのもありかもしれません。
まとめ
cockroachdb/errors と goark/errs のパフォーマンス差異の理由は以下