Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Jan 29, 2016
TOYAMA, Yosaku
System Gr.

DeNA Life Science, Inc.
爆速でAndroi...
⁃ 氏名: 外山 要作
⁃ 所属: DeNAライフサイエンス システムグループ
⁃ 入社: 2012年5月
• 新規サービスの開発、運用
• Android、iOS
⁃ 好きな言語: Ruby と C#
⁃ 趣味: 競プロ、ショートコーディング...
Instant Run など
❌ 爆速でビルドして Android 開発の効率UP
⃝ 爆速でビルドするための仕組みがどうやって成り立っているのか
本日の内容
Copyright (C) DeNA Co.,Ltd. All Rights Res...
⁃ gradle はビルドに時間がかかる
• 上手くやればなんとかできるのでは
• 細々と改良していた
⁃ ところが
• テーマを決めたら → Instant Run !!!
• スライド書いたら → cold swap !!!
経緯
Copy...
⁃ 背景
⁃ トライしていた手法
• hot deploy の困難性
• 実現方法
⁃ Instant Run について
• 推測
⁃ まとめ
アジェンダ
Copyright (C) DeNA Co.,Ltd. All Rights Reser...
ビルド時間を減らすのが大事な理由
⁃ 無駄な時間が減る
⁃ 開発効率の向上
⁃ 小さな単位で結果を確認
背景
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
6
トライしていた手法
7
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
⁃ Java のソースコードを書き換えた結果を手早く確認したい
• ClassLoader をハックできないか
⁃ 上手く行かなかった
• なぜ?
hot deploy の難しさ
Copyright (C) DeNA Co.,Ltd. All ...
DexClassLoader
BaseDexClassLoader#findClass
DexPathList#findClass
DexFile#loadClassBinaryName
DexFile.defineClass
(ここから nativ...
bool dvmAddClassToHash(ClassObject* clazz)
{
// ...
found = dvmHashTableLookup(
gDvm.loadedClasses,
hash,
clazz,
hashcmpCl...
アプリのプロセスを再起動すればなんとかなるのでは!
じゃあどうする?
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
11
⁃ コンパイルした class ごとに dex 化
⁃ 起動時に dex からクラスをロード
• cf. Multidex
⁃ 変更された class のみ転送
具体的な方法
Copyright (C) DeNA Co.,Ltd. All Ri...
⁃ 転送するファイルの特定方法
• Java のコンパイラの性質
⁃ コンパイラに任せてしまえる
優れている点
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
13
⁃ 通常の gradle そのまま
• クリーン後にビルド+インストール → 26 秒
⁃ cf. daemon=false だと 40 秒
• 変更してビルド + インストール → 4.5 秒
⁃ cf. daemon=false だと 18...
Instant Run
15
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
⁃ メソッドの実装の変更、クラスの追加削除は hot swap 可能
⁃ それ以外は大体 cold swap
ふむ。
Instant Run の仕様
Copyright (C) DeNA Co.,Ltd. All Rights Reserved...
⁃ メソッドの実装の変更には対応している
⁃ シグニチャの変更やフィールドの変更に対応していない
⁃ java.lang.reflect.Proxy
• 「動的プロキシのクラスおよびインスタンスを作成するstaticメソッドを提供」
⁃ ふむ。
...
interface Some {
String method_1();
String method_2();
String method_3();
String method_4();
String method_5();
}
このインターフェ...
class QuadSome implements Some {
public String method_1() {
return String.valueOf(1 * 1);
}
public String method_2() {
ret...
Some instance = (Some) Proxy.newProxyInstance(
Some.class.getClassLoader(),
new Class<?>[]{ Some.class },
(proxy, method, ...
⁃ Proxy は interface に対してでしか使えない
⁃ あるクラスXに対して
• メソッドの実装部分を X_0 として切り出す
• X に対するメソッドの呼び出しは X_0 を参照するようにする
• 変更したメソッドの実装部分を X...
class Foo {
public int someField = 123;
public int someMethod() {
return someField + 456;
}
}
模擬コード例
Copyright (C) DeNA Co...
class Foo_0 {
private Foo proxy;
Foo_0(Foo proxy) {
this.proxy = proxy;
}
public int someMethod() {
return ivar.someField ...
public int someMethod() {
return someField + 456;
}
↓↓↓

public int someMethod() {
return someField + 789;
}
メソッドの内容を変更
Co...
class Foo_1 extends Foo {
private Foo proxy;
Foo_1(Foo proxy) {
this.proxy = proxy;
}
public int someMethod() {
return pro...
private Class getDelegate() {
File dex = findLatestDex();
if (dex != loadedDex) {
delegate = loadDex(dex);
loadedDex = dex...
考え得る hot deploy の実現方法
⁃ Jack and Jill
⁃ デバッグ時は Class Loading の制限を解除
余談
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
27
⁃ トライしていた手法
• 転送するファイルの特定方法がシンプル
• プロセスの再起動が必要
• Instant Runェ…
⁃ Instant Run
• hot swap は Activity の再起動すら不要
• (開発時とリリース時の同...
⁃ Bazel
• http://bazel.io/docs/mobile-install.html
• mobile-install —incremental
⁃ Buck
• https://buckbuild.com/article/ex...
Thanks!
30
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Upcoming SlideShare
Loading in …5
×

爆速でAndroidアプリを ビルドするための仕組み DeNA TechCon #denatechcon

10,218 views

Published on

DeNA TechCon 2016 の発表資料です。
Instant Run などの手法がどうやって実現されているかを考察しました。

Published in: Technology
  • Be the first to comment

爆速でAndroidアプリを ビルドするための仕組み DeNA TechCon #denatechcon

  1. 1. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Jan 29, 2016 TOYAMA, Yosaku System Gr.
 DeNA Life Science, Inc. 爆速でAndroidアプリを ビルドするための仕組み
  2. 2. ⁃ 氏名: 外山 要作 ⁃ 所属: DeNAライフサイエンス システムグループ ⁃ 入社: 2012年5月 • 新規サービスの開発、運用 • Android、iOS ⁃ 好きな言語: Ruby と C# ⁃ 趣味: 競プロ、ショートコーディング ⁃ お酒 自己紹介 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 2
  3. 3. Instant Run など ❌ 爆速でビルドして Android 開発の効率UP ⃝ 爆速でビルドするための仕組みがどうやって成り立っているのか 本日の内容 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 3
  4. 4. ⁃ gradle はビルドに時間がかかる • 上手くやればなんとかできるのでは • 細々と改良していた ⁃ ところが • テーマを決めたら → Instant Run !!! • スライド書いたら → cold swap !!! 経緯 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 4
  5. 5. ⁃ 背景 ⁃ トライしていた手法 • hot deploy の困難性 • 実現方法 ⁃ Instant Run について • 推測 ⁃ まとめ アジェンダ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 5
  6. 6. ビルド時間を減らすのが大事な理由 ⁃ 無駄な時間が減る ⁃ 開発効率の向上 ⁃ 小さな単位で結果を確認 背景 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 6
  7. 7. トライしていた手法 7 Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
  8. 8. ⁃ Java のソースコードを書き換えた結果を手早く確認したい • ClassLoader をハックできないか ⁃ 上手く行かなかった • なぜ? hot deploy の難しさ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 8
  9. 9. DexClassLoader BaseDexClassLoader#findClass DexPathList#findClass DexFile#loadClassBinaryName DexFile.defineClass (ここから native) Dalvik_dalvik_system_DexFile_defineClassNative dvmDefineClass findClassNoInit Android の ClassLoader Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 9 ※  dalvik  VM  での話 // ... clazz = dvmLookupClass(descriptor, loader, true); if (clazz == NULL) { // ... if (!dvmAddClassToHash(clazz)) { // ...
  10. 10. bool dvmAddClassToHash(ClassObject* clazz) { // ... found = dvmHashTableLookup( gDvm.loadedClasses, hash, clazz, hashcmpClassByClass, true ); // ... } どこにキャッシュされるか Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 10 ⁃ gDvm はグローバルな変数を保持している • つまり gDvm.loadedClasses はプロセスとライフサイクルが同じ
  11. 11. アプリのプロセスを再起動すればなんとかなるのでは! じゃあどうする? Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 11
  12. 12. ⁃ コンパイルした class ごとに dex 化 ⁃ 起動時に dex からクラスをロード • cf. Multidex ⁃ 変更された class のみ転送 具体的な方法 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 12
  13. 13. ⁃ 転送するファイルの特定方法 • Java のコンパイラの性質 ⁃ コンパイラに任せてしまえる 優れている点 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 13
  14. 14. ⁃ 通常の gradle そのまま • クリーン後にビルド+インストール → 26 秒 ⁃ cf. daemon=false だと 40 秒 • 変更してビルド + インストール → 4.5 秒 ⁃ cf. daemon=false だと 18 秒 ⁃ トライしていた手法 • クリーン後にビルド + インストール → 27.5 秒 • 変更してビルド + インストール + 再起動 → 2.5 秒 ⁃ Instant Run • 変更してビルド+インストール → 3 秒 (Activity の再起動なし) 実演 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 14
  15. 15. Instant Run 15 Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
  16. 16. ⁃ メソッドの実装の変更、クラスの追加削除は hot swap 可能 ⁃ それ以外は大体 cold swap ふむ。 Instant Run の仕様 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 16
  17. 17. ⁃ メソッドの実装の変更には対応している ⁃ シグニチャの変更やフィールドの変更に対応していない ⁃ java.lang.reflect.Proxy • 「動的プロキシのクラスおよびインスタンスを作成するstaticメソッドを提供」 ⁃ ふむ。 Proxy っぽい? Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 17
  18. 18. interface Some { String method_1(); String method_2(); String method_3(); String method_4(); String method_5(); } このインターフェイスに対して 説明 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 18
  19. 19. class QuadSome implements Some { public String method_1() { return String.valueOf(1 * 1); } public String method_2() { return String.valueOf(2 * 2); } public String method_3() { return String.valueOf(3 * 3); } public String method_4() { return String.valueOf(4 * 4); } public String method_5() { return String.valueOf(5 * 5); } } Some instance = new QuadSome(); こういう実装をしたい Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 19
  20. 20. Some instance = (Some) Proxy.newProxyInstance( Some.class.getClassLoader(), new Class<?>[]{ Some.class }, (proxy, method, param) -> { int num = Integer.parseInt(method.getName().substring(7)); return String.valueOf(num * num); } ); 動的にメソッドの実装ができる。 Proxy を使うことで Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 20
  21. 21. ⁃ Proxy は interface に対してでしか使えない ⁃ あるクラスXに対して • メソッドの実装部分を X_0 として切り出す • X に対するメソッドの呼び出しは X_0 を参照するようにする • 変更したメソッドの実装部分を X_1 として切り出す • X は最新の X_n を参照するようにしておく もう一工夫 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 21
  22. 22. class Foo { public int someField = 123; public int someMethod() { return someField + 456; } } 模擬コード例 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 22
  23. 23. class Foo_0 { private Foo proxy; Foo_0(Foo proxy) { this.proxy = proxy; } public int someMethod() { return ivar.someField + 456; } } class Foo { public int someField = 123; private Class getDelegate() { // return Foo_0 instance } public int someMethod() { return getDelegate().someMethod(); } } こう変換してみる Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 23
  24. 24. public int someMethod() { return someField + 456; } ↓↓↓ public int someMethod() { return someField + 789; } メソッドの内容を変更 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 24
  25. 25. class Foo_1 extends Foo { private Foo proxy; Foo_1(Foo proxy) { this.proxy = proxy; } public int someMethod() { return proxy.someField + 789; } } もう一度変換すると Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 25
  26. 26. private Class getDelegate() { File dex = findLatestDex(); if (dex != loadedDex) { delegate = loadDex(dex); loadedDex = dex; } return delegate; } ⁃ Foo_0 と Foo_1 は別クラス扱い • クラスがキャッシュされる問題を回避できる 委譲先を決める箇所の模擬コード Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 26 ※  ここまで推測
  27. 27. 考え得る hot deploy の実現方法 ⁃ Jack and Jill ⁃ デバッグ時は Class Loading の制限を解除 余談 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 27
  28. 28. ⁃ トライしていた手法 • 転送するファイルの特定方法がシンプル • プロセスの再起動が必要 • Instant Runェ… ⁃ Instant Run • hot swap は Activity の再起動すら不要 • (開発時とリリース時の同一性) • (オーバーヘッド) ⁃ クラスがキャッシュされる問題さえなければ…… • さらなる改良に期待 まとめ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 28
  29. 29. ⁃ Bazel • http://bazel.io/docs/mobile-install.html • mobile-install —incremental ⁃ Buck • https://buckbuild.com/article/exopackage.html • exopackage ⁃ LayoutCast • https://github.com/mmin18/LayoutCast • IntelliJ と eclipse に対応 類似ツール Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 29
  30. 30. Thanks! 30 Copyright (C) DeNA Co.,Ltd. All Rights Reserved.

×