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


Published on

ScalaDays 2017 Chicago

Published in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website!
    Are you sure you want to  Yes  No
    Your message goes here

Real World Android Akka

  1. 1. Real World Android Akka Taisuke Oe
  2. 2. Who Am I? Taisuke Oe GitHub: / Twitter: My Work Technical Advisor in Septeni Original, Inc. Organizing taisukeoe @OE_uia BONX Android App ScalaMatsuri
  3. 3. The largest international Scala Conference in Asia. 550-600 participants. Voting session for CFP. Travel support for highly voted speakers. Bi-directional professional translation services. 🍣🍻 Around March next year?
  4. 4. This talk Is About: VoIP client VoIP stands for Voice Over Internet Protocol
  5. 5. Agenda VoIP demo Real world example Why Android Akka? How come does Scala work in Android? Pros & Cons.
  6. 6. VoIP Demo taisukeoe/VoIPAkka
  7. 7. Real World Example
  8. 8. What Is BONX ? Group talk system during outdoor activities Snowboarding Skiing Fishing Cycling ...
  9. 9. BONX Architecture Apps VoIP client Android : Scala iOS : Objective C / Swift Servers API server : Ruby on Rails Voice server : golang Earpiece Special bluetooth headset
  10. 10. Why Android Akka?
  11. 11. Stateful Asynchronous Stream Processing System VoIP is. Upstream Recorder -> some DSP -> Encoder -> Socket Downstream Socket -> Decoder -> some DSP -> Player DSP stands for Digital Signal Processing Every component has its own state, which is typically thread UNsafe.
  12. 12. BONX Must Be Resilient. In outdoor activities, we must handle a tons of errors: Poor network Out of range, and recover from it Hardware I/O errors Bluetooth disconnection If a component has a problem, it has to be recovered.
  13. 13. Even Worse Errors might be discovered in a downstream of root-cause. Root cause has to be xed. Errors have to be propagated in reverse. Broken modules might produce broken audio data. Broken audio data might spoil user's experience. It has to be disposed from its queue.
  14. 14. Summary: Two Requirements of BONX Stateful Concurrent Programming Resiliency
  15. 15. That's Where Akka Comes In! Akka is a toolkit for concurrent programing, resiliency ... and distributed systems (out of scope).
  16. 16. for (Stateful) Concurrent Programming Message driven actor model An actor encapsulates its state unless it exposes explicitly.
  17. 17. Actor with a State Example class PlayActor() extends Actor { private val track: AudioTrack = createNewAudioTrack //state. Thread UN-safe override def preStart(): Unit = override def receive: Receive = { //An actor retrieves and process a message from its mailbox one-at-a-time. case AudioPacketMessage(content:ByteString) => track.write(content.toArray[Byte], 0, content.length) } override def postStop(): Unit = { track.stop() track.flush() track.release() } }
  18. 18. Akka Makes A System Resilient Because Akka handles exceptions very well. Actor hierarchy Restart, Stop or Resume a child actor based on supervisorStrategy Note: Restart via supervisingStrategy keeps messages in it. Monitoring (Death watch) A watcher actor get a Terminated(actorRef) message once a watchee actor stops. Note: subsequent recreation of the actor disposes all messages in it.
  19. 19. Sample Exception Handling by an Actor class ExceptionHandlingActor() extends Actor{ private var childActor:ActorRef = createChildActor override def supervisorStrategy: SupervisorStrategy = OneForOneStrategy(){ //Want to reset all mailboxes case _:BrokenAudioDataException => Stop //At default, child actors will be restarted with keeping their mailbox. case t => super.supervisorStrategy.decider.applyOrElse(t, (_:Any) => Escalate) } def receive = { //Stopped childActor will be recreated. case Terminated(ref) => if(childActor == ref) { context.unwatch(childActor) childActor = createChildActor } } private def createChildActor = { val c = context.child(ChildActor.props) context watch c c } }
  20. 20. Recaps: How Akka Works Great? Stateful Concurrent Programming Actor state encapsulation / Processing a message one-at-a-time without an explicit lock. Resiliency Actor hierarchy or monitoring handles errors as you like. Akka solves VoIP problems (almost)!
  21. 21. Why Do I Say "Almost" ? Some problems cannot be captured by exceptions. An audio driver might get silenced sometimes and doesn't respond to anything. There is no silver bullet. Ask a message and check if Ack will be returned within Timeout . If the Ask gets timeout, stop and re-create a new actor. Please rst consider if you can capture it as an expcetion. This heuristic approach is not often recommended.
  22. 22. How Does Scala Work in Android?
  23. 23. Build Toolchain scalac compiles Scala source codes into Java bytecodes dex in Android SDK translates Java bytecode into Dalvik Executable bytecodes is awesome. It is almost functionally compatible with android standard build system. It works great with other sbt-plugins. scala-android/sbt-android
  24. 24. Android Device Specs Are Good Enough In this couple of years, agship Android devices have: 4 to 10 cores CPU 3 to 4 GB memories Up to around 512MB memory per VM can be used with largeHeap=true con guration.
  25. 25. Q. Should You Use Scala in Android? This decision is up to you. Every technology has trade-o s.
  26. 26. Pros & Cons
  27. 27. Pros Powerful language features, standard library and ecosystem. Concurrent programming Collection API Algebraic Data Type & Pattern Matching Traits Productive 0.5 ~ 1.2 ppl for DevOps and Tuning of BONX Android App for two years. Smaller context-switch cost between client codes and server codes.
  28. 28. Another Android Scala Usecase? Stateless (except Views) concurrent programming view modi cation must run on UIThread in Android.
  29. 29. Scala Offers Better APIs for Concurent Programming Scala standard Future works well. Use your own ExecutionContext for onComplete, andThen or else. UIExecutionContext pattern for UIThread callbacks.
  30. 30. UIExecutionContext Pattern class UIExecutionContext(activity:Activity, reporter: Throwable => Unit) extends ExecutionContext{ def execute(runnable: Runnable): Unit = activity.runOnUiThread(runnable) def reportFailure(t: Throwable): Unit = reporter(t) } Future{ //some heavy calculation }.onComplete{ case Success(result) => //reflect your result on views case Failure(exp) => //show error message }(uiExecutionContext) //Explicitly!
  31. 31. Other Android Scala Projects in Real World Septeni Original Comic app hits 6 million DLs! 47 Degrees also has an Akka modules. GANMA! 47deg/macroid 47deg/nine-cards-v2 47deg/scala-days-android pocorall/scaloid
  32. 32. Cons Method 64k limit per a dex le. Scala standard library jar is too big to be a orded as it is. Proguard or MultiDex must be used. No Java8 support yet Android SDK toolchain still targets Java6+ environment. Akka version has to be 2.3.16, which is marked End-of-Life. You have to be careful for wasting memories. No o cial support by Google nor Lightbend (unlike Kotlin)
  33. 33. Proguard Proguard removes unused classes, elds and methods. Unused means not programatically refereced. Proguard does NOT understand re ections. Akka uses re ection much via Props or .conf le. If Proguard is not con gured properly, then NoClassDefFoundError or NoSuchMethodError are occured at runtime. This is the most painful con guration to use Android Scala.
  34. 34. Do You Need to Con gure Proguard from Scratch? No, absolutely. provides a default setting for Scala standard library jar. This covers and at least. scala-android/sbt-android proguard-con g.txt for akka-actor v2.3.16
  35. 35. For New Libraries How to Con gure Proguard for-Ease.
  36. 36. It's Good Enough As a Starting Point. As long as the library is smallish. For example, you can add one liner to your proguard-con g.txt like: -keep class akka.** { *; } You'll want to revisit proguard-con g later on, when your dex exceeds 64k methods. MultiDex would also be an option. when you release your app.
  37. 37. How to Con gure Proguard Properly. Find and add classes which are used via re ection. grep -r "classOf" . would be the easiest. Check and add all classes which FQCN are listed in .conf le. Add classes which occured NoClassDefFoundError or NoSuchMethodError at runtime.
  38. 38. Proguard-Con g Will Look Like: # Akka configuration # Akka 2.3.16 ## for ### Classes used in reference.conf #### -keep class { *; } #### -keep class { *; } #### -keep class akka.dispatch.UnboundedMailbox { *; } -keep class akka.dispatch.BoundedMailbox { *; } -keep class akka.dispatch.UnboundedDequeBasedMailbox { *; } -keep class akka.dispatch.BoundedDequeBasedMailbox { *; } #### -keep class akka.dispatch.BoundedDequeBasedMessageQueueSemantics { *; } -keep class akka.dispatch.UnboundedMessageQueueSemantics { *; } -keep class akka.dispatch.UnboundedDequeBasedMessageQueueSemantics { *; } -keep class akka.dispatch.DequeBasedMessageQueueSemantics { *; } -keep class akka.dispatch.MultipleConsumerSemantics { *; } #### akka.scheduler.implementation -keep class { *; }
  39. 39. Number of Methods and APK Size Comparison In and 2.3.16 (and Scala 2.11.11) Proguard setting # of methods in dex APK size Keep-all-the-classes of Akka 35033 1132KB 15784 590KBKeep Akka classes only referenced by re ection or conf Disclaimer: This result is based on , and it may vary depending on how many classes you use. my sample
  40. 40. Will Android Support Java8? Google has announced that Android current dex toolchain will support Java8. Java 8 Language Features Support Update - Android Developers Blog It's still uncertain if Android-Java8 support will work with Scala.
  41. 41. After Android Java8 Support Works We might be able to enjoy: Scala 2.12 or above Smaller Scala standard lib jar. Dotty(Scala 3.0) will introduce callgraph analysis from project, that eliminates dead code. (no Proguard!) Akka Streams (2.4 or above) Great abstraction for ow graph, and handy back pressure management. Akka Typed (2.5) You can track Akka 2.5 release notes for exciting news about it. Backo Supervisor (2.4 or above) You can backport Backo Supervisor and ThreadLocalRandom for now. Dotty-Linker
  42. 42. Memory Management Android GC is Concurrent Mark & Sweep. Watch out memory allocation & object creation. WrappedArray#map or other higher functions box every primitive type element. works great. Use ring bu ers for hotspots. ByteString works well for concatenation or slicing. Mutable objects within limited scope are your friend. xuwei_k/nobox
  43. 43. Why not Kotlin? 🎉🎉🎉 for Android/Google o cial support! Kotlin is great for Android, in terms of: Smallish standard library jar. Great IDE integration. I still feel a big advantage in Scala lang functionality & ecosystem. like Akka :)
  44. 44. Conclusion Actor model works well in Android in stateful concurrent programming context. Akka resiliency works great in error-prone situation, like an outdoor activities. BONX Android app fully leverages Akka for its VoIP system.