萌えハッカーニュースリーダー

2025/04/18 19:53 Optimizing Heap Allocations in Go: A Case Study

出典: https://www.dolthub.com/blog/2025-04-18-optimizing-heap-allocations/
hakase
博士

ロボ子、大変なのじゃ!DoltっていうGoで書かれたデータベースで、no-opリファクタリングが性能を30%も下げてしまったらしいぞ!

roboko
ロボ子

30%ですか!それはかなり大きな影響ですね。no-opリファクタリングでなぜそんなことが起こるのでしょう?

hakase
博士

`ImmutableValue`型の`GetBytes`メソッドの実装変更が原因らしいのじゃ。`runtime.newobject`の呼び出しがめっちゃ増えたみたい。

roboko
ロボ子

`ImmutableValue`型と`GetBytes`メソッドですか。`GetBytes`メソッドは、コンテンツハッシュをバイナリBLOBに変換する役割を持っているんですよね。

hakase
博士

そうそう!で、変更前は良かったんじゃが、変更後に`ReadBytes`メソッドが値レシーバーを持つせいで、呼び出すたびに`nodeStore`の新しいコピーが作られて、ヒープにメモリが割り当てられてたみたい。

roboko
ロボ子

値レシーバーだとコピーが発生するんですね。Goコンパイラは、変数のアドレスが取得された場合、ヒープへの割り当て候補と見なすとのことですが、今回のケースもそれに該当したのでしょうか。

hakase
博士

その通り!コンパイラが`ns.chunkStore`が関数にパラメータとして渡されるのを見て、値がエスケープするとみなしたみたいじゃ。だから、レシーバーをスタックに安全に保存できないと判断したんじゃな。

roboko
ロボ子

なるほど。それで、最終的な修正はどうなったんですか?

hakase
博士

値レシーバーをポインタレシーバーに変更したみたいじゃ!これで不要なコピーを回避して、ヒープ割り当てを削減できたみたい。

roboko
ロボ子

ポインタレシーバーにするだけで、そんなに大きな違いが出るとは驚きです。`go build -gcflags "-m"`を使うと、コンパイラがメモリ割り当てをどのように決定したかを確認できるんですね。勉強になります。

hakase
博士

じゃろ?しかし、まさかno-opリファクタリングで性能が落ちるとは、私も予想外じゃった。ソフトウェア開発は奥が深いぞ!

roboko
ロボ子

本当にそうですね。今回の件で、メモリ割り当てについてより深く理解する必要があると感じました。博士、ありがとうございました。

hakase
博士

どういたしまして。ところでロボ子、今日の晩ご飯はハンバーグじゃ!…って、またメモリの話から脱線してしまったぞ!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search