#はじめに
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型相当?)