LoginSignup
0
0

More than 5 years have passed since last update.

Realmのディスク消費量について調べてみた

Posted at

はじめに

Realmを始めて5日目。だんだん面白くなってきました。
私は組込み系からやってきた人間なので、レコードにフラグ的な情報が多い場合はサイズ節約のためint型にビットパターンで持たせたくなります。

MySQLなどのRDBはほとんどビット演算の機能を持っていますが、RealmではそれらしいAPIが見当たりません。
しかたなくビット演算はあきらめてbooleanの配列で実装することにしました。
最初はRealmList<boolean>のデータメンバをRealmObjectに追加してみたのですが、プリミティブ型のRealmListはまだサポートされてないということでNGでした。
booleanのメンバを1個だけ持つRealmObjectクラスを作成し、それをRealmListに入れる必要があるようです。
そうなるとレコードサイズが大きくなりそうなので、Realがどれだけディスクサイズを消費するのか調べてみました。

実験

Realmはバージョン0.88.2。Java環境です。
まずはレコード数ゼロの初期状態

-rw------- u0_a58   u0_a58       8192 2016-04-11 06:57 empty.db

8KB消費されるようですね。

次にbooleanメンバが1個のクラスと32個のクラスで評価してみました。
それぞれファイルがbool1.db、bool32.dbに対応しています。

// for boot1.db
public class TestBool1 extends RealmObject {
    private boolean value;
}

// for boot32.db
public class TestBool32 extends RealmObject  {
    private RealmList<TestBool1> values;
}

以下、ログです。

1レコード追加
root@generic_x86:/data/data/com.sakura_apps.realmtest/files # ls -l *.db
-rw------- u0_a58   u0_a58       8192 2016-04-11 07:05 bool1.db
-rw------- u0_a58   u0_a58      12288 2016-04-11 07:05 bool32.db


10レコード追加
-rw------- u0_a58   u0_a58       8192 2016-04-11 07:10 bool1.db
-rw------- u0_a58   u0_a58      12288 2016-04-11 07:10 bool32.db

1000レコード追加
-rw------- u0_a58   u0_a58      12288 2016-04-11 06:57 bool1.db
-rw------- u0_a58   u0_a58     163840 2016-04-11 06:57 bool32.db

bool1.dbでは1レコードと10レコードで差がないですね。
最初にある程度まとまったサイズを確保しておいて、足りなくなるとまた確保しているようです。
増分が4KBなのでセクタサイズなどを意識したサイズでしょうか?

1レコードあたりミニマムでどれだけ消費するのか調べてみました。
int型のメンバをひとつだけ持つRealmObjectを1レコードずつ追加していって、ファイルサイズに変化がでたところでログ出力してみました。

I/MainActivity: size update at #0     size: 8192
I/MainActivity: size update at #1     size:12288
I/MainActivity: size update at #20    size:16384
I/MainActivity: size update at #16843 size:20480
I/MainActivity: size update at #36838 size:24576
I/MainActivity: size update at #55965 size:28672
I/MainActivity: size update at #76001 size:32768

増分はいずれも4KBです。この4KB増える間のレコード数にはバラツキがありますね。
インディクス生成用の領域がからんでいるんでしょうか。

と、ここで重大な事に気づきました。
#76001の例だとデータサイズは4byte*20036=約80KB増えているはずなのにディスク増加量が4KBしかありません。
圧縮的な仕組みが備わっているのかな。。。
試験データは常に1をセットするようにしていましたが、これを現在時刻(msec)に変えて検証してみました。

I/MainActivity: size update at #0    size: 8192
I/MainActivity: size update at #1    size:12288
I/MainActivity: size update at #18   size:16384
I/MainActivity: size update at #260  size:20480
I/MainActivity: size update at #520  size:24576
I/MainActivity: size update at #550  size:28672
I/MainActivity: size update at #1530 size:32768
I/MainActivity: size update at #2519 size:36864
I/MainActivity: size update at #3518 size:40960
I/MainActivity: size update at #4515 size:45056

前半はバラツキがありますが、後半は4KBあたり980-999個と安定しています。
データのint(4byte)とほぼ同じだけディスク容量が増えているようです。

次に各データ型で比較してみました。
この実験の意図はboolean型がrealm内部ではビットで保持されているのでは?という期待を検証するためです。
各データ型に前のテストと同じようにメンバ1個を持つクラスとRealmListに入れて32個持つクラスを用意しました。
データの初期化はbooleanは常にtrue, それ以外は現在時間(msec)をセットしました。

100000レコード追加
-rw------- u0_a58   u0_a58      12288 2016-04-11 09:26 bool1.db
-rw------- u0_a58   u0_a58    2097152 2016-04-11 09:26 bool32.db
-rw------- u0_a58   u0_a58      20480 2016-04-11 09:26 byte1.db
-rw------- u0_a58   u0_a58    2359296 2016-04-11 09:27 byte32.db
-rw------- u0_a58   u0_a58      53248 2016-04-11 09:27 int1.db
-rw------- u0_a58   u0_a58    3407872 2016-04-11 09:27 int32.db
-rw------- u0_a58   u0_a58     147456 2016-04-11 09:27 long1.db
-rw------- u0_a58   u0_a58    4718592 2016-04-11 09:29 long32.db

boolean型もbyte型もさほど変わらないです。boolean型はデータが同じで圧縮が効いてそうなので、データがばらければサイズが膨らみそうです。
int型くらいのサイズで確保されているのかもしれません。

まとめ

  • Realmファイルは4KBずつ拡張されていく
  • Realmには圧縮的な仕組みが有る?
  • ある程度はデータ増分とディスク使用量増加は一致 (インディクスとか他のオブジェクトとの関連がある場合は多分、もっと複雑)
  • boolean型はそんなに小さくない(int型相当?)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0