派手に Class.new(ActiveRecord::Base) しまくってメモリ大量消費

テーブル名を実行時に取得しなければならないために、実行時にモデルクラスを生成してたら、無遠慮に Class.new してて失敗した件。

細かく説明しませんが、ユーザごとにテーブル定義を決定する様な仕組みを、以下のページでサンプルとして書いたように Class.new(ActiveRecord::Base) して実装していました。
KoshigoeBLOG: メタクラスってなんなんだすか?(1)

その発想(?)自体は別にどうという事でもありませんが、毎回 object_id の異なる同名クラスを作成してしまって問題を引き起こしていた事に気がつきました。何が問題かというと、永続的なプロセスの中で、何度も ActiveRecord::Base を継承した同名テーブルの(object_id の異なる)モデルクラスを作成してしまうと、GC されずにメモリに積み上がっていくという事です。

以下のコードの通り、ActiveRecord::Base を継承する度に、ActiveRecord::Base の @@subclasses[] に派生クラスが登録される様です。

module ActiveRecord
  ...
  class Base
    ...
    def self.inherited(child) #:nodoc:
      @@subclasses[self] ||= []
      @@subclasses[self] << child
      super
    end
    ...
end

未だ Rails の事をよくわかっていないのでこれ以上は(少なくとも今は)書きませんが、今までだいぶ浮かれポンチな事をしていたな、と。

でも、すっきりして一安心です。

プロフィール

このブログ記事について

このページは、koshigoeが2009年10月14日 00:20に書いたブログ記事です。

ひとつ前のブログ記事は「REE 1.8.7p174 を Snow Leopard にインストール」です。

次のブログ記事は「Snow Leopard に MacPorts でインストールした Ruby が遅いという話を聞いたけど…」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。