私の歴史と今

振り返ると恥ずかしくなるのが私の歴史。だけどそのときは真面目に書いていた訳でね。そんな今の私を書いていく。

Railsのスレッドセーフ

Rails2.2からスレッド対応になったと聞いていたけど、スレッドセーフなのか気になって調べてみた。単に、コントローラインスタンスがリクエスト毎に作成されることを確かめただけ。
scaffoldで作成したコントローラに対して下記を書く。

p self.object_id

いくつかリクエストを投げると、以下の主力が得られた。

3602
3654
3706
3758

よしよし。リクエスト毎にコントローラオブジェクトが異なっている。
もう少し詳しく見てみよう。クラス変数として配列オブジェクトを作成し、リクエスト毎に作成されるインスタンスを格納していこう。このようにすれば、リクエストの度に配列サイズが増えていくはず。
下記のように、毎回、配列サイズを出力する。

  @@a = []

  def index
    p self.object_id
    @@a.push self
    p @@a.size
  end

何回かリクエストを投げると、

4494
1
4546
1
4598
1
4650
1
4702
1
4754
1

あれれ・・・。予想に反する。配列の要素数がなぜ増えない?? クラス変数なのにインスタンス間で共有されていない・・・。というか、リクエスト毎にクラス自体が別物になっちゃってる??? うー、理解できない。
検索したところ、微熱 everydayを発見。次のように書いてあった。

production ではクラスの再ロードは基本されない。のでコントローラ等で内部DSL るため

そういうことか。developmentでは、リクエスト毎にクラスをロードしてるってことだね。そういえば、どこかで読んだ記憶がある。
RAILS_ENV=productionとして実行すると、期待した結果となった。

2752
1
2756
2
2760
3
2764
4

よしよし。しかしなぜ挙動を変えているんだ? 
もしかして、そういうこと?? 知らなかった。Rubyって、ソースを変更したらすぐ反映されるものだと思ってた。それがスクリプト言語の特徴なのだと思っていた。だけど、productionモードだと、上記の出力をコメントアウトにしても、即時に反映されない。つまり、最初にロードされたままになっている。これがRubyのデフォルトの挙動なのかな。これでは開発しにくい。開発時は、APサーバ起動後、頻繁にコードを変更するからリクエスト毎にクラスロードが走らないと困る。
あー知らなんだ。勉強になった。