Watson's Blog

RubyMotion の Autorelease_pool の使い方

| Comments

この記事は RubyMotion Advent Calendar 2012 の 10 日目の記事です。

つい最近ようやく RubyMotion API Reference が公開されましたが、みなさん見ていただけたでしょうか?RubyMotion のバグを取っていて、「このメソッド初めて見るんだけど何もの?」「ドキュメントが必要だよねぇ」みたいなやりとりをしながら、一生懸命リファレンスを作りました。

今回は autorelease_pool の使い方について書きます。

メモリサイクル

iOS では、ボタンをタップなどするとイベントが発生します。イベントの開始時に自動的にメモリプールを生成し、イベント終了時にプールをリリースします。このときメモリプールに登録されている不要になったオブジェクトが一緒にリリースされます。

RubyMotion で作られたアプリも、これに従って不要になったオブジェクトが破棄されていきます。

たとえば、イベント処理中に以下のような大量の一時的なオブジェクトを作成してみます。

1
2
3
4
5
  100000.times do
    "abc"
    [1, 2, 3]
    {"foo" => 42}
  end

Instruments.app でメモリ使用を確認すると、以下のようになります。

autorelease_pool なし

イベントが終了するまで一時的なオブジェクトは生存していて、イベント終了とともに破棄されている様子がわかります。

最近の iOS デバイスはメモリを 512 MB 以上搭載していますが、どうしてもメモリの使用量を抑えながら処理をしたい場合があるかと思います。

autorelease_pool を使ってみよう

上のコードを次のように変更します。

1
2
3
4
5
6
7
  100000.times do
    autorelease_pool {
      "abc"
      [1, 2, 3]
      {"foo" => 42}
    }
  end

autorelease_pool のブロックで囲むようにしただけです。Objective-C の @autorelease ブロックと同じようですね。

Instruments.app でメモリ使用を確認してみます。

autorelease_pool なし

今回は一定のメモリ使用率をキープしていることが分かります。autorelease_pool ブロックの処理が終わると、ブロック内で使用した不要なオブジェクトが破棄されていることが分かるかと思います。

autorelease_pool を使うとメモリ使用量を抑えることができますが、メモリプールの生成とリリースがそのたびに行われるのでそのぶん処理時間が延びます。まだ作りこみが足りてないようで、autorelease_pool で破棄されているオブジェクトにアクセスするとクラッシュするのでご注意ください。

Comments