SlideShare ist ein Scribd-Unternehmen logo
1 von 66
What mom never told
you… about
multi-threading
@fernando_cejas
hello!
I am Fernando Cejas
I am here because I love to share experiences and
disasters I have made in my professional life...
You can find me at @fernando_cejas or
http://fernandocejas.com
hello!
A picture is worth a thousand words
These are MOM and
SISTER…
...grabbing a BEER...
A picture is worth a thousand words
May the FORCE of
MULTI-THREADING
be with you...my SON...
“Multithreading is not
easy...multithreading is hard.
“Redesigning your application to
run multithreaded on a
multicore machine is a little like
learning to swim by jumping into
the deep end.
“The wall is there. We probably
won't have any more products
without multicore processors
[but] we see a lot of problems in
parallel programming.
1.
We are not multi-tasking
Humans are capable of doing two things at a time especially when
one of those activities is so ingrained that it can be done on
autopilot.
2.
...but computers are!!!
Computer can run things in parallel concurrently.
But what does that mean exactly?
Concurrent
Concurrency is about dealing with A LOT of
things...
Concurrency vs Parallelism
What is the difference?
Parallel
Parallelism is about doing A LOT of things
at ONCE.
This talk is really about THREADING...
...RxJava
...Threads
and Locks
...Kotlin
Coroutines
and maybe something else...
And not about Android...
HandlersAsyncTasks JobScheduler
Let’s review some concepts
Process
It is an instance of a computer
program that is being executed. It
contains the program code and its
current activity.
Thread
It is the smallest sequence of
programmed instructions that can
be managed independently by a
scheduler, which is typically a part of
the operating system.
Mutability
A mutable object can be changed
after it's created, and an immutable
object can't.
Deadlock
Describes a situation where two or
more threads are blocked forever,
waiting for each other.
Race Condition
Occurs when two or more threads
can access shared data and they try
to change it at the same time. Both
threads are "racing" to
access/change this data.
Starvation
Describes a situation where a thread
is unable to gain regular access to
shared resources and is unable to
make progress.
✘ When an application component starts and the
application does not have any other components running,
the Android system starts a new Linux process for the
application with a single thread of execution.
✘ By default, all components of the same application run in
the same process and thread (called the "main" thread).
✘ Android might decide to shutdown a process at some
point, when memory is low and required by other
processes that are more immediately serving the user.
Application components running in the process that's
killed are consequently destroyed.
Android
Linux process:
- UI Thread
Why
Multithreading?It is always IMPORTANT to know the
fundamentals but...
Responsiveness
Concurrency can ensure improved
responsiveness of a program that interacts
with the environment.
Resources
Use resources in a better and more
performant way.
Simplicity
Concurrency can simplify the
implementation and maintainability of
computer programs. Divide and conquer.
A simple problem on Android
Get
Wikipedia
Pages
Grab text
from each
Page
Count
words
occurrence
✘ https://github.com/android10/Multi-Threading-Samples
We will be parsing 2 XML files of 30 MB each with Wikipedia content.
“FIRST, make code work, THEN
make it right, THEN make it
fast…if it isn’t fast enough.
In my defense...FOR LEARNING PURPOSE....
1.
Threads and Locks
class SequentialWordCount {
private val counts: HashMap<String, Int?> = HashMap()
fun run() {
val time = measureTimeMillis {
Thread {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}.start()
}
Log.d(LOG_TAG, "Number of elements: ${counts.size}")
Log.d(LOG_TAG, "Execution Time: $time ms")
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
1.
Threads and Locks
Run sequentially
21.678 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.threads.SequentialWordCount: Number of elements:
196681
com.fernandocejas.sample.threading.threads.SequentialWordCount: Execution Time: 21678 ms
2
Threads and Locks
Run Two Threads
class TwoThreadsWordCount {
private val counts: ConcurrentHashMap<String, Int?> = HashMap()
fun run() {
val time = measureTimeMillis {
val one = Thread {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
val two = Thread {
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
one.start(); two.start(); one.join(); two.join()
}
Log.d(LOG_TAG, "Number of elements: ${counts.size}")
Log.d(LOG_TAG, "Execution Time: $time ms")
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
18.427 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.threads.TwoThreadsWordCount: Number of elements:
196.681
com.fernandocejas.sample.threading.threads.TwoThreadsWordCount: Execution Time: 18427 ms
2.
Rx Java
“RxJava is more than a framework
for dealing with multithreading.
Concurrency is ONLY one of its
features.
Use the best tool for the right job.
What are RxJava Schedulers?
✘ If you want to introduce
multithreading into your cascade of
Observable operators, you can do so
by instructing those operators (or
particular Observables) to operate
on particular Schedulers.
Observable.just("Hello World")
.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.UI)
2.
RxJava 2
Run sequentially
class SequentialWordCount {
private val counts: HashMap<String, Int?> = HashMap()
fun run() {
val startTime = System.currentTimeMillis()
val observable = Observable.fromCallable {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
observable
.doOnComplete { logData(System.currentTimeMillis() - startTime) }
.subscribeOn(Schedulers.single())
.subscribe()
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
20.920 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Number of elements: 196681
com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Execution Time: 20920 ms
2.
RxJava 2
Run Two Threads
class TwoThreadsWordCount {
private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap()
fun run() {
val startTime = System.currentTimeMillis()
val observablePagesOne = Observable.fromCallable {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
}.subscribeOn(Schedulers.newThread())
val observablePagesTwo = Observable.fromCallable {
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}.subscribeOn(Schedulers.newThread())
observablePagesOne.mergeWith(observablePagesTwo)
.doOnComplete { logData(System.currentTimeMillis() - startTime) }
.subscribe()
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
17.256 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.rxjava.TwoThreadsWordCount: Number of elements: 196681
com.fernandocejas.sample.threading.rxjava.TwoThreadsWordCount: Execution Time: 17256 ms
3.
Kotlin Coroutines
What are kotlin coroutines?
✘ Coroutines are light-weight threads. A
lightweight thread means it doesn’t map
on native thread, so it doesn’t require
context switching on processor, so they
are faster.
✘ They are a way to write asynchronous
code sequentially. Instead of running into
callback hells, you write your code lines
one after the other.
fun main(args: Array<String>) = runBlocking {
val job = launch(CommonPool) {
val result = suspendingFunction()
println("$result")
}
println("The result: ")
job.join()
}
>> prints "The result: 5"
3
Kotlin Coroutines
Run sequentially
class SequentialWordCount {
private val counts: HashMap<String, Int?> = HashMap()
fun run() {
launch(newSingleThreadContext("myThread")) {
val startTime = System.currentTimeMillis()
counter()
logData(System.currentTimeMillis() - startTime)
}
}
private suspend fun counter() {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
20.958 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.coroutines.SequentialWordCount: Number of elements:
196681
com.fernandocejas.sample.threading.coroutines.SequentialWordCount: Execution Time: 20958 ms
3
Kotlin Coroutines
Run Two Threads
class TwoThreadsWordCount {
private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap()
fun run() {
val poolContext = newFixedThreadPoolContext(2, "ThreadPool")
launch(poolContext) {
val time = measureTimeMillis {
val one = async(poolContext) { counterPages1() }
val two = async(poolContext) { counterPages2() }
one.await()
two.await()
}
logData(time)
}
}
private suspend fun counterPages1() {
val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
private suspend fun counterPages2() {
val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
}
18.980 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.coroutines.TwoThreadsWordCount: Number of elements:
196681
com.fernandocejas.sample.threading.coroutines.TwoThreadsWordCount: Execution Time: 18980 ms
Round 1 Results
Single Thread Two Threads Better?
Threads and
Locks
21.678 ms 18.427 ms ???
RxJava 2 20.920 ms 17.256 ms ???
Kotlin
Coroutines
20.958 ms 18.980 ms ???
Adding one thread does not have a big impact...
What is really going on?
Hypothesis: ???
We can do better!
✘ Producer - Consumer pattern?
✘ Divide and Conquer?
✘ Reusing Threads?
✘ Other synchronized collections?
Some advice!
✘ Analyze the problem.
✘ Verify your assumptions.
✘ Measure, measure, measure.
✘ Measure, measure, measure.
Hypothesis 1: Am I using the right concurrent collection
for storing data?
Concurrent collections?
2.
RxJava 2
Run Two Threads
class TwoThreadsWordCount {
private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap()
fun run() {
val startTime = System.currentTimeMillis()
val observablePagesOne = Observable.fromCallable {
val pagesOne = Pages(0, 5000, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
}.subscribeOn(Schedulers.newThread())
val observablePagesTwo = Observable.fromCallable {
val pagesTwo = Pages(0, 5000, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}.subscribeOn(Schedulers.newThread())
observablePagesOne.mergeWith(observablePagesTwo)
.doOnComplete { logData(System.currentTimeMillis() - startTime) }
.subscribe()
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
Verifying assumptions:
parallel collections
Test started for: class java.util.Hashtable
500K entried added/retrieved in 1432 ms
500K entried added/retrieved in 1425 ms
500K entried added/retrieved in 1373 ms
500K entried added/retrieved in 1369 ms
500K entried added/retrieved in 1438 ms
For class java.util.Hashtable the average time 1407 ms
Test started for: class java.util.Collections$SynchronizedMap
500K entried added/retrieved in 1431 ms
500K entried added/retrieved in 1460 ms
500K entried added/retrieved in 1387 ms
500K entried added/retrieved in 1456 ms
500K entried added/retrieved in 1406 ms
For class java.util.Collections$SynchronizedMap the average time 1428 ms
Test started for: class java.util.concurrent.ConcurrentHashMap
500K entried added/retrieved in 413 ms
500K entried added/retrieved in 351 ms
500K entried added/retrieved in 427 ms
500K entried added/retrieved in 337 ms
500K entried added/retrieved in 339 ms
For class java.util.concurrent.ConcurrentHashMap the average time 373 ms <== Much faster
Hypothesis 2: XML parsing?
I/0: Reading from disk?
2.
RxJava 2
Run sequentially
class SequentialWordCount {
private val counts: HashMap<String, Int?> = HashMap()
fun run() {
val startTime = System.currentTimeMillis()
val observable = Observable.fromCallable {
val pagesOne = Pages(0, 5000, Source().wikiPagesBatchOne())
pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } }
val pagesTwo = Pages(0, 5000, Source().wikiPagesBatchTwo())
pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } }
}
observable
.doOnComplete { logData(System.currentTimeMillis() - startTime) }
.subscribeOn(Schedulers.single())
.subscribe()
}
private fun countWord(word: String) {
when(counts.containsKey(word)) {
true -> counts[word] = counts[word]?.plus(1)
false -> counts[word] = 1
}
}
}
Measuring:
Measure and Measure
com.fernandocejas.sample.threading.rxjava.SequentialWordCount: PageOne creation time: 15 ms
com.fernandocejas.sample.threading.rxjava.SequentialWordCount: PageTwo creation time: 13 ms
com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Total Execution Pages Creation: 28 ms
com.fernandocejas.sample.threading.data.Pages: Time Parsing XML File: 4062 ms
com.fernandocejas.sample.threading.data.Pages: Time Processing XML Node Elements: 611 ms
com.fernandocejas.sample.threading.data.Pages: Total Time: 4673 ms
com.fernandocejas.sample.threading.data.Pages: Time Parsing XML File: 4360 ms
com.fernandocejas.sample.threading.data.Pages: Time Processing XML Node Elements: 631 ms
com.fernandocejas.sample.threading.data.Pages: Total Time: 4991 ms
What are the BOTTLENECKS
and FIRST CONCLUSIONS?
Threads being idle waiting for I/0.
Locking the map when adding elements.
We can do better!
✘ Producer - Consumer pattern?
✘ Divide and Conquer?
✘ Reusing Threads?
✘ Other synchronized collections?
4
Better solution
Kotlin Coroutines
class BetterWordCount(source: Source) {
fun run() {
launch(CommonPool) {
val time = measureTimeMillis {
val one = async(CommonPool) { counter(0.rangeTo(749), filePagesOne) }
val two = async(CommonPool) { counter(750.rangeTo(1500), filePagesOne) }
val three = async(CommonPool) { counter(0.rangeTo(749), filePagesTwo) }
val four = async(CommonPool) { counter(750.rangeTo(1500), filePagesTwo) }
one.await(); two.await(); three.await(); four.await()
}
logData(time)
}
}
private suspend fun counter(range: IntRange, file: File): HashMap<String, Int?> {
val counts: HashMap<String, Int?> = HashMap()
val pagesOne = Pages(range.start, range.endInclusive, file)
pagesOne.forEach { page -> Words(page.text).forEach { countWord(counts, it) } }
return counts
}
}
14.621 millisExecution time
196.681 words found
Two 30 MB XML files processed on an android device
com.fernandocejas.sample.threading.coroutines.BetterWordsCount: Number of elements: 196781
com.fernandocejas.sample.threading.coroutines.BetterWordsCount: Execution Time: 14621 ms
Round 2 Results
Single Thread Two Threads Better?
Threads and
Locks
21.678 ms 18.427 ms ???
RxJava 2 20.920 ms 17.256 ms ???
Kotlin
Coroutines
20.958 ms 18.980 ms 14.621 ms
We can do better!
Homework!
Write sample code:
✘ Using Threads and Locks
✘ Using Kotlin Coroutines
✘ Using a pure FP Language
Contribute!
✘ https://github.com/android10/Multi-Threading-Samples
Facing multithreading problems:
✘ Debugging.
✘ Mutability.
✘ Performance.
✘ Testing.
✘ Sharing state.
✘ ???
...that is why is important to know the fundamentals and building blocks.
Verdict?
1. Use the right tool for the right job.
2. Always measure.
3. No silver bullets.
“FIRST, make code work, THEN
make it right, THEN make it
fast…if it isn’t fast enough.
TODO (to explore):
✘ Memory Consumption.
✘ Android Threading Components.
✘ External Libraries.
✘ iOS Threading Model.
✘ Server Side Multithreading.
Contribute!
✘ https://github.com/android10/Multi-Threading-Samples
Out of curiosity
Other threading approaches:
✘ Actor Model
✘ FP Languages:
○ Clojure
○ Scala
○ Haskel
Wrapping up...
Responsiveness
Concurrency can ensure
improved responsiveness,
favoring better user
experiences and faster
applications.
Resources
By running tasks in parallel, the
use of resources is better and
more performant.
Simplicity
Multithreading is not easy...but
in many cases can simplify the
design of your system by using
a divide and conquer approach.
thanks!
Any questions?
You can find me here:
@fernando_cejas
http://fernandocejas.com
github.com/android10
Credits
Special thanks to all the people who made and released
these awesome resources for free:
✘ Presentation template by SlidesCarnival
✘ Photographs by Unsplash

Weitere ähnliche Inhalte

Ähnlich wie Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading

node.js, javascript and the future
node.js, javascript and the futurenode.js, javascript and the future
node.js, javascript and the future
Jeff Miccolis
 
Slot02 concurrency1
Slot02 concurrency1Slot02 concurrency1
Slot02 concurrency1
Viên Mai
 
HTML5 Multithreading
HTML5 MultithreadingHTML5 Multithreading
HTML5 Multithreading
Allan Huang
 
Multithreading
MultithreadingMultithreading
Multithreading
backdoor
 
Beginning MEAN Stack
Beginning MEAN StackBeginning MEAN Stack
Beginning MEAN Stack
Rob Davarnia
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
Dinh Pham
 
Introto netthreads-090906214344-phpapp01
Introto netthreads-090906214344-phpapp01Introto netthreads-090906214344-phpapp01
Introto netthreads-090906214344-phpapp01
Aravindharamanan S
 

Ähnlich wie Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading (20)

Hidden pearls for High-Performance-Persistence
Hidden pearls for High-Performance-PersistenceHidden pearls for High-Performance-Persistence
Hidden pearls for High-Performance-Persistence
 
Comet with node.js and V8
Comet with node.js and V8Comet with node.js and V8
Comet with node.js and V8
 
The art of messaging tune (Joker 2015 edition)
The art of messaging tune (Joker 2015 edition)The art of messaging tune (Joker 2015 edition)
The art of messaging tune (Joker 2015 edition)
 
node.js, javascript and the future
node.js, javascript and the futurenode.js, javascript and the future
node.js, javascript and the future
 
Slot02 concurrency1
Slot02 concurrency1Slot02 concurrency1
Slot02 concurrency1
 
Java concurrency
Java concurrencyJava concurrency
Java concurrency
 
Lessons from Highly Scalable Architectures at Social Networking Sites
Lessons from Highly Scalable Architectures at Social Networking SitesLessons from Highly Scalable Architectures at Social Networking Sites
Lessons from Highly Scalable Architectures at Social Networking Sites
 
HTML5 Multithreading
HTML5 MultithreadingHTML5 Multithreading
HTML5 Multithreading
 
Multi Threading
Multi ThreadingMulti Threading
Multi Threading
 
Node.js: A Guided Tour
Node.js: A Guided TourNode.js: A Guided Tour
Node.js: A Guided Tour
 
The Theory Of The Dom
The Theory Of The DomThe Theory Of The Dom
The Theory Of The Dom
 
Multithreading
MultithreadingMultithreading
Multithreading
 
Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!
 
Beginning MEAN Stack
Beginning MEAN StackBeginning MEAN Stack
Beginning MEAN Stack
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
 
Introto netthreads-090906214344-phpapp01
Introto netthreads-090906214344-phpapp01Introto netthreads-090906214344-phpapp01
Introto netthreads-090906214344-phpapp01
 
FlinkForward Asia 2019 - Evolving Keystone to an Open Collaborative Real Time...
FlinkForward Asia 2019 - Evolving Keystone to an Open Collaborative Real Time...FlinkForward Asia 2019 - Evolving Keystone to an Open Collaborative Real Time...
FlinkForward Asia 2019 - Evolving Keystone to an Open Collaborative Real Time...
 
Sherlock Homepage - A detective story about running large web services - WebN...
Sherlock Homepage - A detective story about running large web services - WebN...Sherlock Homepage - A detective story about running large web services - WebN...
Sherlock Homepage - A detective story about running large web services - WebN...
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 

Mehr von MobileFest2018

Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложенийMobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
MobileFest2018
 

Mehr von MobileFest2018 (13)

Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile PoetsMobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
Mobile Fest 2018. Enrique López Mañas. TensorFlow for Mobile Poets
 
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexyMobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy
 
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOSMobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
Mobile Fest 2018. Алексей Демедецкий. Отладка с архитектурой Redux на iOS
 
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
Mobile Fest 2018. Илья Иванов. Как React-Native перевернул наше представление...
 
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
Mobile Fest 2018. Владимир Бондаренко. Почему переход с Apache Cordova на Rea...
 
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background RestrictionsMobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
Mobile Fest 2018. Yonatan Levin. WTF with Android Background Restrictions
 
Mobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great againMobile Fest 2018. Алексей Лизенко. Make your project great again
Mobile Fest 2018. Алексей Лизенко. Make your project great again
 
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
Mobile Fest 2018. Артем Гетьман. Архитектура обработки ошибок: чистый, быстры...
 
Mobile Fest 2018. Кирилл Розов. Insert Koin
Mobile Fest 2018. Кирилл Розов. Insert KoinMobile Fest 2018. Кирилл Розов. Insert Koin
Mobile Fest 2018. Кирилл Розов. Insert Koin
 
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложенийMobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
Mobile Fest 2018. Алеся Подлесная. UX в разработке мобильных приложений
 
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
Mobile Fest 2018. Александр Сергиенко. Flutter - что за зверь такой?
 
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
Mobile Fest 2018. Håvard Hvassing. Working with sharp tools — continuous inte...
 
Mobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. БолеутоляющееMobile Fest 2018. Александр Корин. Болеутоляющее
Mobile Fest 2018. Александр Корин. Болеутоляющее
 

Kürzlich hochgeladen

The basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptxThe basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptx
heathfieldcps1
 

Kürzlich hochgeladen (20)

Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfUnit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
 
Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...
 
Interdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptxInterdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptx
 
SOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning PresentationSOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning Presentation
 
How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17
 
Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptx
 
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptxHMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.ppt
 
Sociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning ExhibitSociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning Exhibit
 
Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docx
 
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptxHMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
 
FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024
 
How to Create and Manage Wizard in Odoo 17
How to Create and Manage Wizard in Odoo 17How to Create and Manage Wizard in Odoo 17
How to Create and Manage Wizard in Odoo 17
 
How to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POSHow to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POS
 
Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024
 
General Principles of Intellectual Property: Concepts of Intellectual Proper...
General Principles of Intellectual Property: Concepts of Intellectual  Proper...General Principles of Intellectual Property: Concepts of Intellectual  Proper...
General Principles of Intellectual Property: Concepts of Intellectual Proper...
 
The basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptxThe basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptx
 
This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.
 
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
 

Mobile Fest 2018. Fernando Cejas. What Mom Never Told You About Multi-threading

  • 1. What mom never told you… about multi-threading @fernando_cejas
  • 2. hello! I am Fernando Cejas I am here because I love to share experiences and disasters I have made in my professional life... You can find me at @fernando_cejas or http://fernandocejas.com
  • 4. A picture is worth a thousand words These are MOM and SISTER… ...grabbing a BEER...
  • 5. A picture is worth a thousand words May the FORCE of MULTI-THREADING be with you...my SON...
  • 7. “Redesigning your application to run multithreaded on a multicore machine is a little like learning to swim by jumping into the deep end.
  • 8. “The wall is there. We probably won't have any more products without multicore processors [but] we see a lot of problems in parallel programming.
  • 9. 1. We are not multi-tasking Humans are capable of doing two things at a time especially when one of those activities is so ingrained that it can be done on autopilot.
  • 10. 2. ...but computers are!!! Computer can run things in parallel concurrently. But what does that mean exactly?
  • 11. Concurrent Concurrency is about dealing with A LOT of things... Concurrency vs Parallelism What is the difference? Parallel Parallelism is about doing A LOT of things at ONCE.
  • 12. This talk is really about THREADING... ...RxJava ...Threads and Locks ...Kotlin Coroutines and maybe something else...
  • 13. And not about Android... HandlersAsyncTasks JobScheduler
  • 14. Let’s review some concepts Process It is an instance of a computer program that is being executed. It contains the program code and its current activity. Thread It is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system. Mutability A mutable object can be changed after it's created, and an immutable object can't. Deadlock Describes a situation where two or more threads are blocked forever, waiting for each other. Race Condition Occurs when two or more threads can access shared data and they try to change it at the same time. Both threads are "racing" to access/change this data. Starvation Describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress.
  • 15. ✘ When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. ✘ By default, all components of the same application run in the same process and thread (called the "main" thread). ✘ Android might decide to shutdown a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process that's killed are consequently destroyed. Android Linux process: - UI Thread
  • 16. Why Multithreading?It is always IMPORTANT to know the fundamentals but...
  • 17. Responsiveness Concurrency can ensure improved responsiveness of a program that interacts with the environment.
  • 18. Resources Use resources in a better and more performant way.
  • 19. Simplicity Concurrency can simplify the implementation and maintainability of computer programs. Divide and conquer.
  • 20. A simple problem on Android Get Wikipedia Pages Grab text from each Page Count words occurrence ✘ https://github.com/android10/Multi-Threading-Samples We will be parsing 2 XML files of 30 MB each with Wikipedia content.
  • 21. “FIRST, make code work, THEN make it right, THEN make it fast…if it isn’t fast enough. In my defense...FOR LEARNING PURPOSE....
  • 23. class SequentialWordCount { private val counts: HashMap<String, Int?> = HashMap() fun run() { val time = measureTimeMillis { Thread { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } }.start() } Log.d(LOG_TAG, "Number of elements: ${counts.size}") Log.d(LOG_TAG, "Execution Time: $time ms") } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } } 1. Threads and Locks Run sequentially
  • 24. 21.678 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.threads.SequentialWordCount: Number of elements: 196681 com.fernandocejas.sample.threading.threads.SequentialWordCount: Execution Time: 21678 ms
  • 25. 2 Threads and Locks Run Two Threads class TwoThreadsWordCount { private val counts: ConcurrentHashMap<String, Int?> = HashMap() fun run() { val time = measureTimeMillis { val one = Thread { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } } val two = Thread { val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } } one.start(); two.start(); one.join(); two.join() } Log.d(LOG_TAG, "Number of elements: ${counts.size}") Log.d(LOG_TAG, "Execution Time: $time ms") } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 26. 18.427 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.threads.TwoThreadsWordCount: Number of elements: 196.681 com.fernandocejas.sample.threading.threads.TwoThreadsWordCount: Execution Time: 18427 ms
  • 28. “RxJava is more than a framework for dealing with multithreading. Concurrency is ONLY one of its features. Use the best tool for the right job.
  • 29. What are RxJava Schedulers? ✘ If you want to introduce multithreading into your cascade of Observable operators, you can do so by instructing those operators (or particular Observables) to operate on particular Schedulers. Observable.just("Hello World") .subscribeOn(Schedulers.computation()) .observeOn(Schedulers.UI)
  • 30. 2. RxJava 2 Run sequentially class SequentialWordCount { private val counts: HashMap<String, Int?> = HashMap() fun run() { val startTime = System.currentTimeMillis() val observable = Observable.fromCallable { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } } observable .doOnComplete { logData(System.currentTimeMillis() - startTime) } .subscribeOn(Schedulers.single()) .subscribe() } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 31. 20.920 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Number of elements: 196681 com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Execution Time: 20920 ms
  • 32. 2. RxJava 2 Run Two Threads class TwoThreadsWordCount { private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap() fun run() { val startTime = System.currentTimeMillis() val observablePagesOne = Observable.fromCallable { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } }.subscribeOn(Schedulers.newThread()) val observablePagesTwo = Observable.fromCallable { val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } }.subscribeOn(Schedulers.newThread()) observablePagesOne.mergeWith(observablePagesTwo) .doOnComplete { logData(System.currentTimeMillis() - startTime) } .subscribe() } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 33. 17.256 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.rxjava.TwoThreadsWordCount: Number of elements: 196681 com.fernandocejas.sample.threading.rxjava.TwoThreadsWordCount: Execution Time: 17256 ms
  • 35. What are kotlin coroutines? ✘ Coroutines are light-weight threads. A lightweight thread means it doesn’t map on native thread, so it doesn’t require context switching on processor, so they are faster. ✘ They are a way to write asynchronous code sequentially. Instead of running into callback hells, you write your code lines one after the other. fun main(args: Array<String>) = runBlocking { val job = launch(CommonPool) { val result = suspendingFunction() println("$result") } println("The result: ") job.join() } >> prints "The result: 5"
  • 36. 3 Kotlin Coroutines Run sequentially class SequentialWordCount { private val counts: HashMap<String, Int?> = HashMap() fun run() { launch(newSingleThreadContext("myThread")) { val startTime = System.currentTimeMillis() counter() logData(System.currentTimeMillis() - startTime) } } private suspend fun counter() { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 37. 20.958 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.coroutines.SequentialWordCount: Number of elements: 196681 com.fernandocejas.sample.threading.coroutines.SequentialWordCount: Execution Time: 20958 ms
  • 38. 3 Kotlin Coroutines Run Two Threads class TwoThreadsWordCount { private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap() fun run() { val poolContext = newFixedThreadPoolContext(2, "ThreadPool") launch(poolContext) { val time = measureTimeMillis { val one = async(poolContext) { counterPages1() } val two = async(poolContext) { counterPages2() } one.await() two.await() } logData(time) } } private suspend fun counterPages1() { val pagesOne = Pages(0, 700, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } } private suspend fun counterPages2() { val pagesTwo = Pages(0, 700, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } } }
  • 39. 18.980 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.coroutines.TwoThreadsWordCount: Number of elements: 196681 com.fernandocejas.sample.threading.coroutines.TwoThreadsWordCount: Execution Time: 18980 ms
  • 40. Round 1 Results Single Thread Two Threads Better? Threads and Locks 21.678 ms 18.427 ms ??? RxJava 2 20.920 ms 17.256 ms ??? Kotlin Coroutines 20.958 ms 18.980 ms ???
  • 41. Adding one thread does not have a big impact... What is really going on? Hypothesis: ???
  • 42. We can do better! ✘ Producer - Consumer pattern? ✘ Divide and Conquer? ✘ Reusing Threads? ✘ Other synchronized collections?
  • 43. Some advice! ✘ Analyze the problem. ✘ Verify your assumptions. ✘ Measure, measure, measure. ✘ Measure, measure, measure.
  • 44. Hypothesis 1: Am I using the right concurrent collection for storing data? Concurrent collections?
  • 45. 2. RxJava 2 Run Two Threads class TwoThreadsWordCount { private val counts: ConcurrentHashMap<String, Int?> = ConcurrentHashMap() fun run() { val startTime = System.currentTimeMillis() val observablePagesOne = Observable.fromCallable { val pagesOne = Pages(0, 5000, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } }.subscribeOn(Schedulers.newThread()) val observablePagesTwo = Observable.fromCallable { val pagesTwo = Pages(0, 5000, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } }.subscribeOn(Schedulers.newThread()) observablePagesOne.mergeWith(observablePagesTwo) .doOnComplete { logData(System.currentTimeMillis() - startTime) } .subscribe() } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 46. Verifying assumptions: parallel collections Test started for: class java.util.Hashtable 500K entried added/retrieved in 1432 ms 500K entried added/retrieved in 1425 ms 500K entried added/retrieved in 1373 ms 500K entried added/retrieved in 1369 ms 500K entried added/retrieved in 1438 ms For class java.util.Hashtable the average time 1407 ms Test started for: class java.util.Collections$SynchronizedMap 500K entried added/retrieved in 1431 ms 500K entried added/retrieved in 1460 ms 500K entried added/retrieved in 1387 ms 500K entried added/retrieved in 1456 ms 500K entried added/retrieved in 1406 ms For class java.util.Collections$SynchronizedMap the average time 1428 ms Test started for: class java.util.concurrent.ConcurrentHashMap 500K entried added/retrieved in 413 ms 500K entried added/retrieved in 351 ms 500K entried added/retrieved in 427 ms 500K entried added/retrieved in 337 ms 500K entried added/retrieved in 339 ms For class java.util.concurrent.ConcurrentHashMap the average time 373 ms <== Much faster
  • 47. Hypothesis 2: XML parsing? I/0: Reading from disk?
  • 48. 2. RxJava 2 Run sequentially class SequentialWordCount { private val counts: HashMap<String, Int?> = HashMap() fun run() { val startTime = System.currentTimeMillis() val observable = Observable.fromCallable { val pagesOne = Pages(0, 5000, Source().wikiPagesBatchOne()) pagesOne.forEach { page -> Words(page.text).forEach { countWord(it) } } val pagesTwo = Pages(0, 5000, Source().wikiPagesBatchTwo()) pagesTwo.forEach { page -> Words(page.text).forEach { countWord(it) } } } observable .doOnComplete { logData(System.currentTimeMillis() - startTime) } .subscribeOn(Schedulers.single()) .subscribe() } private fun countWord(word: String) { when(counts.containsKey(word)) { true -> counts[word] = counts[word]?.plus(1) false -> counts[word] = 1 } } }
  • 49. Measuring: Measure and Measure com.fernandocejas.sample.threading.rxjava.SequentialWordCount: PageOne creation time: 15 ms com.fernandocejas.sample.threading.rxjava.SequentialWordCount: PageTwo creation time: 13 ms com.fernandocejas.sample.threading.rxjava.SequentialWordCount: Total Execution Pages Creation: 28 ms com.fernandocejas.sample.threading.data.Pages: Time Parsing XML File: 4062 ms com.fernandocejas.sample.threading.data.Pages: Time Processing XML Node Elements: 611 ms com.fernandocejas.sample.threading.data.Pages: Total Time: 4673 ms com.fernandocejas.sample.threading.data.Pages: Time Parsing XML File: 4360 ms com.fernandocejas.sample.threading.data.Pages: Time Processing XML Node Elements: 631 ms com.fernandocejas.sample.threading.data.Pages: Total Time: 4991 ms
  • 50. What are the BOTTLENECKS and FIRST CONCLUSIONS? Threads being idle waiting for I/0. Locking the map when adding elements.
  • 51. We can do better! ✘ Producer - Consumer pattern? ✘ Divide and Conquer? ✘ Reusing Threads? ✘ Other synchronized collections?
  • 52. 4 Better solution Kotlin Coroutines class BetterWordCount(source: Source) { fun run() { launch(CommonPool) { val time = measureTimeMillis { val one = async(CommonPool) { counter(0.rangeTo(749), filePagesOne) } val two = async(CommonPool) { counter(750.rangeTo(1500), filePagesOne) } val three = async(CommonPool) { counter(0.rangeTo(749), filePagesTwo) } val four = async(CommonPool) { counter(750.rangeTo(1500), filePagesTwo) } one.await(); two.await(); three.await(); four.await() } logData(time) } } private suspend fun counter(range: IntRange, file: File): HashMap<String, Int?> { val counts: HashMap<String, Int?> = HashMap() val pagesOne = Pages(range.start, range.endInclusive, file) pagesOne.forEach { page -> Words(page.text).forEach { countWord(counts, it) } } return counts } }
  • 53. 14.621 millisExecution time 196.681 words found Two 30 MB XML files processed on an android device com.fernandocejas.sample.threading.coroutines.BetterWordsCount: Number of elements: 196781 com.fernandocejas.sample.threading.coroutines.BetterWordsCount: Execution Time: 14621 ms
  • 54. Round 2 Results Single Thread Two Threads Better? Threads and Locks 21.678 ms 18.427 ms ??? RxJava 2 20.920 ms 17.256 ms ??? Kotlin Coroutines 20.958 ms 18.980 ms 14.621 ms
  • 55. We can do better!
  • 56. Homework! Write sample code: ✘ Using Threads and Locks ✘ Using Kotlin Coroutines ✘ Using a pure FP Language
  • 58. Facing multithreading problems: ✘ Debugging. ✘ Mutability. ✘ Performance. ✘ Testing. ✘ Sharing state. ✘ ??? ...that is why is important to know the fundamentals and building blocks.
  • 59. Verdict? 1. Use the right tool for the right job. 2. Always measure. 3. No silver bullets.
  • 60. “FIRST, make code work, THEN make it right, THEN make it fast…if it isn’t fast enough.
  • 61. TODO (to explore): ✘ Memory Consumption. ✘ Android Threading Components. ✘ External Libraries. ✘ iOS Threading Model. ✘ Server Side Multithreading.
  • 63. Out of curiosity Other threading approaches: ✘ Actor Model ✘ FP Languages: ○ Clojure ○ Scala ○ Haskel
  • 64. Wrapping up... Responsiveness Concurrency can ensure improved responsiveness, favoring better user experiences and faster applications. Resources By running tasks in parallel, the use of resources is better and more performant. Simplicity Multithreading is not easy...but in many cases can simplify the design of your system by using a divide and conquer approach.
  • 65. thanks! Any questions? You can find me here: @fernando_cejas http://fernandocejas.com github.com/android10
  • 66. Credits Special thanks to all the people who made and released these awesome resources for free: ✘ Presentation template by SlidesCarnival ✘ Photographs by Unsplash