Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyでメモリリークを作成する方法|実例コードで仕組みを理解する

メモリリークの「見つけ方」を解説した記事は数多く存在します。

しかし、逆に「作り方」についてはどうでしょうか?

意図的にメモリリークを作ってみることは、Rubyにおけるメモリリークがどのような挙動を示すのかを理解するための良い演習になると考えています。

それでは、いくつかの具体例を見ていきましょう。

シンプルなメモリリーク

最も簡単なメモリリークの作り方は、配列に新しいオブジェクトを追加し続けることです。

以下のようなコードです:

a = []
b = {}

loop {
  sleep(1)

  10_000.times { a << "abc" }

  puts GC.stat(b)[:heap_live_slots]
}

このコードは毎秒1万個の文字列オブジェクトを生成し、同時にライブスロット数を出力します:

285051
295052
305053
315054
325055
335056
345057
355058

このカウントが増え続けるのは、GC(ガベージコレクタ)がこれらの文字列を回収できないためです。文字列は配列 a から参照され続けているからですね。

もし変数 a がスコープ外に出れば、GCはこれらの "abc" 文字列をすべて回収できるようになります。実際に試すには、上記のコードで a = nil を実行してから GC.start を呼び出してみてください。

ブラウザ上で動かせるライブサンプルも用意しています。run ボタンをクリックすれば、結果をその場で確認できます。

C拡張によるメモリリーク

Ruby上でオブジェクトを生成した場合、GCはそのメモリ使用量を追跡できます。しかし、C拡張(C Extension)を使う場合、Rubyはその内部で何が起きているかを制御できません。

例えば、次のようなC拡張を作ったとしましょう:

#include <ruby.h>
#include "extconf.h"

void *ptr;

void Init_extension()
{
  allocate_memory();
}

void allocate_memory() {
  for(int i = 0; i < 10000; i++) {
   ptr = malloc(1000);
  }
}

この allocate_memory() 関数は、malloc で確保したメモリに対して free を呼び出していないため、メモリリークが発生します。

実際にプロセスのメモリ使用量(RSS)を確認すると、次のようになります:

`ps -o rss -p #{$$}`.lines.last
# "49036"

require './extension'

`ps -o rss -p #{$$}`.lines.last
# "89512"

この種のリークは、ヒープダンプや GC.stat の統計情報には一切現れません。しかし、プロセス全体のメモリ使用量は着実に増加していきます。

まとめ

これで、Rubyにおけるメモリリークがどのようなものかイメージできたのではないでしょうか。実際にメモリリークの問題に直面した際、この知識が原因特定のスピードアップにつながれば幸いです。

ちなみに、Ruby 2.4.1には既知のメモリリークが存在します。該当バージョンを使用している場合は、アップグレードを検討することをおすすめします。

質問やフィードバック、そして面白いメモリリークのデバッグ体験談などがあれば、ぜひコメント欄でお聞かせください 🙂

最後までお読みいただきありがとうございました!


  1. Google Chromeのメモリ使用量が多い?メモリリークの原因と対処法を徹底解説

    Google Chromeは軽快な動作とシンプルなインターフェースで、世界中で愛用されているブラウザです。筆者もその圧倒的なスピード感が気に入っており、アドオンが多く動作の重いFirefoxや、どうしても遅くなりがちなInternet ExplorerよりもChromeを選んできました。Microsoft EdgeはIEよりかなり高速になりましたが、GmailやGoogleドライブなどGoogleサービスを多用する身としては、やはりChromeが一番しっくりきます。ちなみに、新エンジン「Quantum」を搭載したFirefoxはChromeより速いとも言われており、乗り換えを本気で検討したこと

  2. Windows 11でエクスプローラーのメモリリークを解決する方法【原因と対処法を徹底解説】

    Windows 11にアップグレードした後、「メモリリーク」の問題に悩まされていませんか?実は多くのユーザーがWindows 11への更新後に同様のトラブルを報告しています。この記事では、エクスプローラー(File Explorer)のメモリリークを解決するための具体的な対処法をわかりやすく紹介します。メモリリークとは?メモリリークとは、アプリやシステムプロセスが不要になった後もRAM(メインメモリ)やシステムリソースを解放せず、確保し続けてしまう現象のことです。特定のメモリ領域が解放されないままになると、使用可能なRAMが徐々に減少し、PCの動作が遅くなります。最悪の場合、システムのフリーズ