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.

Real world android akka

3,154 views

Published on

Scala Kansai 2016

Published in: Software
  • Be the first to comment

Real world android akka

  1. 1. Real World Android Akka
  2. 2. Who am I? 麻植泰輔 / Taisuke Oe Twitter: @OE_uia GitHub: taisukeoe 会社 - BONX INC. でAndroidアプリ書いたりスノー ボードするお仕事 - ScalaMatsuri座長 / Japan Scala Association, Inc.常務理事 個人 - Scalaを教える仕事しています
  3. 3. スポンサー募集 CFP スタッフ募集 OPEN!!
  4. 4. What’s the topic? 本日のお話
  5. 5. 本日のお話 Android + Scala + Akka ⇓ VoIPクライアント
  6. 6. 本日のお話 ◉ Akka ○ メッセージ駆動 ○ Actorの実行モデル ○ Actorのヒエラルキー ◉ BONX ○ BONXとは? ○ BONX VoIPクライアントの要求仕様 ◉ Android Akkaの注意点 ○ Dispatcher, Mailboxの実装など ◉ Scala Androidってどうなの?
  7. 7. Akka?
  8. 8. Akka ◉ メッセージ駆動で並行/分散処理するtoolkit ◉ Lightbend CTO Jonas Bonér氏が作者 ◉ 名前の由来はスイスの先住民の神様 ◉ スイスのLaponiaという山がAkka神のシンボル
  9. 9. Message Driven? メッセージ駆動?
  10. 10. メッセージ駆動 Actorがメッセージを送り合い協調動作することで、システムを構成 あとはたのむ
  11. 11. メッセージ駆動 あとはたのむ 次に手が空いてから やるわ Actorが受け取ったメッセージは、そのActorに紐付いたMailboxに入る
  12. 12. メッセージ駆動 あとはたのむ 次に手が空いてから やるわ Actorはメッセージ一つ一つを逐次処理する => (特にスレッドセーフではない)状態管理を伴う並行プログラミングに有用
  13. 13. メッセージ駆動 あとはたのむ 今からやるお Actorは他のActorについては、メッセージの送信先と受け取れるメッセージ の種類についてのみ知っておけばよいため、Actor同士を疎結合にしやす い
  14. 14. Akka Dispatcher Actorの実行モデル
  15. 15. Actorの実行モデル Thread Thread Dispatcher DispatcherがActorの実行基盤。内部にThreadPoolを保持。
  16. 16. Actorの実行モデル Thread Thread Dispatcher 1つのActorは、同時に一つのスレッドにだけ割り振られる
  17. 17. Actorの実行モデル Thread Thread Dispatcher Threadが空いたら、次のActorが割り振られる
  18. 18. Actorの実行モデル Dispatcher Actorは、Mailboxにメッセージが有り、なおかつThreadが割り 当てられてるときにメッセージを処理する
  19. 19. Actorプログラミングのアンチパターン Thread Thread Dispatcher Actorが長時間Threadをブロックすると、同じdispatcherを使用 しているActorシステム全体の処理が進みにくくなる 進捗ダメです
  20. 20. Akka Actor Hierarchy Actorのヒエラルキー
  21. 21. Actorの階層構造 Dispatcher Actorには親子関係が作れる ワシが育てた
  22. 22. Actorの階層構造 Dispatcher 子ActorでThrowableが投げられると、親Actorの supervisorStrategy関数が呼ばれる _人人人人人人人人人_ > 突然のThrowable <  ̄Y^Y^Y^Y^Y^Y^Y^Y ̄
  23. 23. Actorの階層構造 Dispatcher supervisorStrategyの実装により、その後の子Actorの処遇が 決定される Restart
  24. 24. Akkaについて - まとめ ◉ Actorがメッセージを送り合うことでシステムを構成 ◉ 1つのActorは同時に1メッセージを1スレッドで逐次処 理するため、状態管理が楽 ◉ 実行モデル ○ Dispatcher … Thread(pool)の保持と、ActorへのThread貸 出 ○ Mailbox … Actorに送られたメッセージ置き場 ◉ ActorのヒエラルキーとSupervisorStrategyの実装を 適切に設定することで、障害からの回復力をもつ
  25. 25. The Way We Talk BONX
  26. 26. BONXとは? 野外の激しい運動中でも 複数の仲間とスムーズに コミュニケーションとれるVoIPサービス VoIP = Voice over Internet Protocol
  27. 27. Requirement specification in BONX VoIP client BONX VoIPクライアントの要求仕様
  28. 28. BONX VoIPクライアントの要求仕様 ◉ 状態管理を伴う並行プログラミング ◉ (それなりに)低遅延 ◉ 障害からの回復力
  29. 29. VoIPは音声ストリーム処理 ソケット通信録音 音量調整 発話検知 エンコード デコード再生
  30. 30. 音声ストリーム処理: 並行プログラミング ◉ 1フレームの処理が終わる前に、次のフレームの音声デー タが送られてくる ◉ 必然的に並行プログラミングすることになる ◉ しかしエンコーダー・デコーダーなどのモジュールは、多く の場合Threadセーフではない Actorモデル向き
  31. 31. 低遅延 ◉ 合計の遅延:大きくなりすぎると、(特に顔が見えていると き)通話中に違和感 ◉ 個々の遅延:フレーム間の遅延が大きくなりすぎると、「ブ ツッ」という音の途切れの原因 Dispatcher, Mailboxのカスタマイズ性は必要十分
  32. 32. 障害からの回復力 ◉ クライアントアプリとしては長時間(~8時間)の連続使用を想 定 ◉ 使用中、録音/再生のハードウェア I/Oなど一部のモ ジュールに問題が発生するケースがある ◉ 何かの状態がおかしい場合は、関連するモジュール含め て、自動で再初期化が必要 AkkaのActorヒエラルキーを適切に設定しておくと、モジュール 群を自動で再初期化することで障害から回復できる
  33. 33. Pitfalls in Android Akka Android Akkaの注意点
  34. 34. Android Akkaの注意点 ◉ Akka version ◉ Proguard設定 ◉ Dispatcherの罠 ◉ Mailboxのサイズ
  35. 35. Akka version ◉ AndroidはJava6/7相当の環境 ◉ Akka 2.14系はJava8要求 => Akka 2.13系を使う
  36. 36. Proguard ● Akkaはapplication.confやPropsを基に、リフレクションで Actorなどをインスタンス化 ● Proguardは使用されていないクラス、メソッドをバイトコード から抜くpost-processingツール ● Proguardはリフレクションを理解しない ● Android ScalaにおけるNoSuchMethodErrorの発生原因 の殆どはProguard起因 => proguard.cfgに随時指定 参考: Macroid | Akka Integration
  37. 37. Dispatcherの罠 application.confのparallerism-factorは、(min~maxの範囲 で)availableProcessorsに乗じた数のThreadPoolを作る akka.dispatch.ThreadPoolConfig object ThreadPoolConfig { /* … */ def scaledPoolSize(floor: Int, multiplier: Double, ceiling: Int): Int = math.min(math.max((Runtime.getRuntime.availableProcessors * multiplier).ceil.toInt, floor), ceiling) /* … */ }
  38. 38. AndroidのavailableProcessors Androidの場合、電力消費を抑えるため、高クロックと低クロックのコア から構成されているヘテロCPUが主流。そのため、一度に全てのCPUコ アがonlineにならない端末が多い。 しかしRuntime#availableProcessorsは常に全合計コア数を返す。この 数字をそのまま使うと、Thread数がコア数に対して多くなりすぎてパ フォーマンスが低下することがある /sys/devices/system/cpu/online では 1-5,6 のようにオンライン状態の CPUのindexをチェックできる (参考:Linux kernel related to hotplug a CPU)
  39. 39. カスタムDispatcher akka.dispatcher.ExecutorServiceConfiguratorを継承 したクラスのFQCN(フル修飾名)をapplication.confに指定 可能 my-dispatcher { type = Dispatcher executor = "com.taisukeoe.MyExecutorConfigurator" fork-join-executor { parallerism-min = 8 parallerism-factor = 2 parallerism-max = 16 } }
  40. 40. カスタム ExecutorServiceConfigurator class MyExecutorConfigurator(config: Config, prerequisites: DispatcherPrerequisites) extends ExecutorServiceConfigurator(config, prerequisites) { final def createExecutorServiceFactory(id: String, threadFactory: ThreadFactory): ExecutorServiceFactory = { val c = config.getConfig("fork-join-executor") new ForkJoinExecutorServiceFactory( threadFactory.asInstanceOf[ForkJoinPool.ForkJoinWorkerThreadFactory], CPUConfig.scaledPoolSize( c.getInt("parallelism-min"), c.getDouble("parallelism-factor"), c.getInt("parallelism-max")), true) } }
  41. 41. OnlineのCPUコア数を取得 object CPUConfig { private lazy val rangeRegex = "([0-9]+)-([0-9]+)".r def onlineProcessors: Option[Int] = Try { val reader = new BufferedReader(new FileReader("/sys/devices/system/cpu/online")) val num = Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq.headOption map { cpu:String => cpu.split(",").map { case rangeRegex(from, to) => to.toInt - from.toInt + 1 case num => 1 }.sum reader.close() num }}.toOption.flatten def scaledPoolSize(floor: Int, multiplier: Double, ceiling: Int): Int = math.min(math.max(onlineProcessors.getOrElse(Runtime.getRuntime.availableProcessors) * multiplier).ceil.toInt, floor), ceiling) }
  42. 42. Mailboxのサイズ ◉ Androidは(増えてきたとはいえ)基本的には低メモリ環境 ◉ 1 VM ~ 数百MB RAM ◉ サイズ制限のないMessageBoxだとOutOfMemoryErrorのおそれ ◉ できるだけ有限サイズのMailbox (BoundedMailbox) を使う方が 良い ◉ それで必要要件をみたさないときは、カスタムMailboxを作るべき 参考: Mailboxes -- Akka my-mailbox { mailbox-type = "com.taisukeoe.MyMailBox" }
  43. 43. Android Scala Pros & Cons ScalaでAndroidってどうなの?
  44. 44. ScalaでAndroidってどうなの? ◉ ScalaとAndroid両方に詳しい人がチームに1人いたら選択肢として アリ。チーム2人目以降は、どちらかについて詳しければ、教育可能 ◉ sbt-androidが(クセはあるけど)とても優秀。組み合わせると便利な sbt pluginも色々 ◉ 今回のケースではScala + Akka + Androidのメリットが存分に活き た ○ 常時1~2人分の工数の少人数チームで新規機能開発&メンテ ○ 必要な低遅延/スループットなどのパフォーマンスを達成しつ つ、モジュールの疎結合化、コードの抽象化に(それなりに)成
  45. 45. ScalaでAndroidってどうなの? ◉ 万人にオススメはしない ◉ ScalaとAndroid両方の知識がそれなりに必要 ◉ ビルドが長い (Proguardのせい) ◉ Googleのサポート外 ○ Scala2.12 & Java8対応? ■ Jack & JillがJava8対象 ○ Jack & Jill対応? ■ sbt-androidにPullReqは一応....
  46. 46. まとめ ◉ Akkaはメッセージ駆動で並行/分散処理を便利に行える toolkit ◉ Androidでも幾つかのポイントに注意すれば、Akkaは十分 実用的である。 ◉ VoIPアプリの音声ストリーム処理など、AndroidでもActor モデルが非常に有用となるケースがある
  47. 47. We’re hiring! ◉ VoIPクライアントアプリに興味がある人 ◉ Android Scalaを触ってみたい人 ◉ Akkaのチューニングをゴリゴリしたい人 ◉ スノボ、サイクリング 等々が好きな人 お気軽に @OE_uia までメッセください

×