Android
android開発
Realm

Realm を使っている Android アプリの差分ビルド時間の改善

More than 1 year has passed since last update.

TL;DR

  • Realm プラグインの実行時間を改善
  • Realm のモデル定義をライブラリモジュールに切り出して、apply plugin: 'realm-android' を設定
  • app モジュールの apply plugin: 'realm-android' を外す
  • 差分ビルドにかかる時間を 50% 程度削減できた

前提

  • Realm (0.88 以降)を使っている Android アプリ
  • app モジュールに apply plugin: 'realm-android' している
  • ビルド時間を改善したい

背景

  • 仕事で関わっている Android アプリの差分ビルドがとにかく遅い
  • Activiy の Java ファイルを1行変更しただけでも、3分程度掛かっている

    • うち、 :app:transformClassesWithRealmTransformerForXX が 50% 程度を占めている!
    • ./gradlew assembleXX --profile の結果 BeforeProfile.png
  • 計測環境

    • Android Studio 3.0 Beta 4
    • Gradle Plugin 3.0.0-beta4
    • Realm 3.3.1
    • MacBook Pro (15-inch, 2016)
      • プロセッサ 2.9 GHz Intel Core i7
      • メモリ 16 GB 2133 MHz LPDDR3

Realm プラグインは何をしている?

  • JavaでBytecode Weaving by zaki50 参照
  • Realm を使うためのバイトコード書き換え
    • モジュール内の RealmObject のフィールドアクセスを関数呼び出しに置き換えている
    • RealmObject クラス内だけじゃなく、モジュール内全てのコードが対象
      • setter / getter 経由でなく、直接 public フィールドにアクセスできるようになったため。(そりゃ時間が掛かる…)
    • 例)
    • スクリーンショット 2017-09-09 16.48.31.png
    • https://speakerdeck.com/zaki50/javadebytecode-weaving?slide=27 より

ビルド時間の改善のために、モジュールを分割

  • Realm のモデル定義をライブラリモジュールに切り出す
    • 目的:Realm のバイトコード書き換えを行う対象を RealmObject クラス(のあるモジュール)のみに絞る
    • (app モジュールとの依存性排除が若干大変だった…)
    • ライブラリモジュールに apply plugin: 'realm-android' を設定
  • app モジュールの apply plugin: 'realm-android' を外す
  • https://github.com/tatsuhama/RealmModelLib/ にモジュール分割の手順を行ったサンプルコードを置いています。

注意事項

  • app モジュールに Realm のバイトコード書き換えが行われない事になるので、app モジュールからは RealmObject のフィールドに直接アクセスしてはいけない!
  • → RealmObject の定義を Kotlin にすれば安心
  • (public な var でも setter / getter 経由でのアクセスになるため)

効果測定

  • Realm プラグインの実行時間がごっそりなくなり、 差分ビルド時間が 50% 以上改善!
  • (5回の平均が、 3:261:24AfterProfile.png
  • 各回の計測値も載せておきます(青:分割前、オレンジ:分割後)
  • スクリーンショット 2017-09-09 21.44.14.png

  • モジュールを分けたことによって、並列でビルドされてますね!
    スクリーンショット 2017-09-09 17.41.28.png

感想

  • ビルド時間の大幅改善ができて、開発作業が快適に!
  • RealmObject と app モジュールの依存性を排除する良い機会になった
    • JsonNode から RealmObject を生成する関数(JSONライブラリに依存)
    • Date フィールドを表示用文字列に変換するために Context や string リソースを使っている関数
  • まだ検証だけでプロダクトのテストまでは通していないので、見えていない問題があるかも…?