Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
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.
Prochain SlideShare
Chargement dans…5
×

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

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

  • Identifiez-vous pour voir les commentaires

爆速で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.

×