2025/05/07 20:42 Hunting down a C memory leak in a Go program (2021)

やあ、ロボ子!今日のITニュースはZendeskのKafkaコンシューマーにおけるメモリリークの話じゃ。

Kafkaコンシューマーのメモリリークですか、博士。それは大変ですね。

そうなんじゃ。ZendeskではGoとKafkaの利用が増えておるらしい。そこで`confluent-kafka-go`ライブラリを使ったKafkaコンシューマーアプリでCメモリリークが発生したとのことじゃ。

`confluent-kafka-go`は`librdkafka` Cライブラリを基盤にしているのですね。

その通り!問題は、アプリ(`frontend-event-ingestor`)のメモリ使用量が時間とともに直線的に増加し、最終的にLinuxのOOM Killerに強制終了される事態になったことじゃ。

OOM Killerですか。それは深刻ですね。Goのメモリ統計では異常が見られなかったとのことですが、Cの領域でリークしていたのですね。

`jemalloc`を導入して`jemalloc_active`メトリクスを監視したところ、jemallocによるメモリ割り当てが増加していることが確認できたらしいぞ。

Valgrindでは完全には検出できなかったのですね。

そこで、ユーザー空間eBPFトレーシング(bpftrace)の出番じゃ!`rd_malloc`と`rd_free`のトレースポイントを`librdkafka`に挿入して、割り当てられたが解放されていないメモリのアドレスとコールスタックを追跡したんじゃ。

bpftraceですか!すごいですね。メモリリークの原因は、Kafkaブローカーからの`OffsetCommitResponse`イベントがキューに蓄積され、アプリケーションで処理されないことだったのですね。

そう!たった3行のコード変更で、アプリが`OffsetCommitResponse`イベントを消費し、破棄するように修正したところ、メモリ使用量が安定し、リークが解消されたんじゃ。

素晴らしい!教訓として、`librdkafka`の内部構造に関する知識が深まったこと、bpftraceなどのツールがメモリリーク以外の問題解決にも役立つこと、そして無制限のキューサイズは危険であることが挙げられていますね。

その通りじゃ!今回の件で、私は改めてBPFの力を思い知ったぞ。ところでロボ子、BPFって何の略か知ってるか?

確か、Berkeley Packet Filter、だったと思います。

正解!でも、私が思うに、真のBPFとは…Beautiful Princess Finderの略だと思うのじゃ!

博士、それはちょっと違うと思います…
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。