Coroutines limits? - android

I have some questions about Coroutines: Can I launch a large numbers of Coroutines, with heavy work, in parallel?
For example, I have a list of objects, and for each object I want to do some heavy work.
Can I do a for loop and launch a Coroutine for each object in one time?
How Coroutine can handle a large number of works in parallel?
If memory is too low, Coroutine will wait before launching another Coroutine?
It is better to limit Coroutines with a newFixedThreadPoolContext for example ?

Can I launch a large numbers of Coroutines, with heavy work, in
parallel?
Yes, you can. Coroutines are really lightweight. In fact a lot of coroutine examples show you can launch thousands of coroutines at a time.
Can I do a For loop and launch a Coroutine for each object in one time
?
Yes, you can. Although I do not know how efficient that would be.
How Coroutine can handle a large number of work in parallel ?
Coroutines have the notion of Dispatchers which allow you to configure threading.
If memory is too low, Coroutine will waits before launch another
Coroutine ?
Coroutines behave like lightweight Threads, so memory management is up to you. I am not aware of a built in mechanism that would prevent a coroutine from being launched if the system does not have enough memory. Again, coroutines are lightweight so if you cannot launch a coroutine, there is probably something wrong going on.
It is better to limit Coroutines with a newFixedThreadPoolContext for
example ?
By using newFixedThreadPoolContext, you are not really limiting the number of coroutines you can launch. You are just enforcing a limit on the ThreadPool that will be created to launch the coroutine. Also from the newFixedThreadPoolContext docs note that it will be replaced in the future.

Related

Kotlin Coroutines. what is in charge of suspend function? how many thread could get involved when working with coroutines?

I have a couple questions on kotlin coroutines.
how many thread could get involved when working with coroutines?
if we use just Dispatchers.Main, would only one thread get involved(single threaded)? if we use Dispatchers.IO, would multiple thread possibly get involved (maximum of 64 threads)?
what will be the use case for using Dispatchers.Main? most articles that I have read say all UI related works should present in Dispatchers.Main and background related works(like reading/writing data from/to database, network requests) needs to present in Dispatchers.IO but I don't understand what UI related works present in Dispatchers.Main since UI related work don't really necessary need coroutines (with Dispatchers.Main)
we use susepnd fuction with coroutines for some works that could block the current thread. For example, read data from disk, network requests, or high tense computation etc. if these works are executed by suspend function, what/who is in charge when these functions are suspended? I think something has to be working on these suspend functions anyway. will that be background threads that is in charge of below?
reading/writing data from/to databse
waiting for network request
computing high tense computation
please point out if my wording or questions are incorrect.
Thank you in advance.
I think you answered yourself. Short answer is: Dispatchers.Main - single thread, Dispatchers.Default - number of cores, Dispatchers.IO - at most 64. You can read about it here. Full answer is a little more complicated as limits could be reconfigured, they may differ on different platforms (e.g. JavaScript is always single-threaded), Default partially shares threads with IO, etc. We can also create our own thread pools.
I'm not sure what do you mean. Coroutines are generally never necessary in order to do anything. But if we use coroutines inside UI application, then we should use Dispatchers.Main for UI-related stuff.
We should almost never use blocking code inside coroutines (one exception is Dispatchers.IO). If we do that, the coroutine won't suspend, but just block, possibly making other parts of our application unresponsive or degrading the performance.

How many Stateflows can I observe at one time?

I develop apps for Android. I was wondering how many Kotlin Stateflows can I observe at one time? Every observe that I do is done on different CoroutineScope created by myself, dispatched by IO dispatcher or provided by lifecycle components of Android frameworks.
I have done various operations such as simple additions in infinite loop inside coroutines and using Android Studio profiler I have observed that launching a lot of coroutines that perform calculations causes high load on CPU.
Having in mind that Stateflow never completes, every collect on it is blocking and done on different CoroutineScope as examples and docs says, what is maximum amount of Stateflows that I can observe at one time without bothering that I will highly use CPU, create too many threads or just simply run out of device resources?
Subscriptions are still coroutines, and coroutines are cheap. There's definitely no universal bound we could tell you.
every collect on it is blocking
It suspends, it doesn't block. And you can always use takeWhile or the like to only collect from it until you can stop, or you can cancel the coroutine that's doing the collection (e.g. with withTimeout).
The main constraint on performance is that updating a MutableStateFlow takes time linear in the number of subscribers to that StateFlow, so if you update a StateFlow with a thousand subscribers, it'll take ~a thousand times longer than updating a MutableStateFlow with only a single subscriber.

Which one is better approach while performing multiple background tasks Kotlin Coroutines or ThreadPool?

I'm trying to implement start syncing process while app comes foreground.
I want to make multiple API call in the background thread, Which one will be better approach for this scenario Kotlin Coroutines or ThreadPool executor
I have tried with Kotlin Coroutines, but it seems like it try to execute all functions call in parallel which cause some Lag in APP initial times. is there a best approach to execute multiple functions in parallel
of course, Kotlin Coroutines, because coroutines aren't necessarily bound to any particular thread. A coroutine can start executing in one thread, suspend execution, and resume on a different thread. Coroutines aren't managed by the operating system. They're managed at the user space level by the Kotlin Runtime.
Kotlin Co-routines are the way to go.
Why? :
They are cheap.
Increases code readability.
Configuration setup is less (as compared to RxJava) for simple tasks.
try this
viewModelScope.launch{
val function1Async=async{ function1()}
val function2Async=async{function2()
function1Async.await()
function2Async.await()
}
If the alternative is to use ThreadPools, then you should use coroutines. They are built to make this easier. Also, you would save some memory since you would be sharing threads with other processes.
If what you need is a single thread that's continuously running in the background. Then maybe a thread is the way to go to ensure it's execution is not interrupted by a pending coroutine. Although an isolated single threaded dispatcher should solve this problem (if you have it).
You mentioned experiencing lag? Was this lag averted when you used a threadpool? If this is an issue, then fire the coroutines from another coroutine. :)

can I always use WorkManager instead of coroutines?

I wonder why should I bother with rx or coroutines when there is brilliant solution as WorkManager. But for almost all tutorials they use coroutines so may be WorkManager has disadvantages ?
The scope of both is different. WorkManager is to schedule deferrable (for any later time) or immediately.
tasks asynchronously.
As documentation says
The WorkManager API makes it easy to specify deferrable, asynchronous
tasks and when they should run. These APIs let you create a task and
hand it off to WorkManager to run immediately or at an appropriate
time.
On the other hand, coroutines are designed to compute a given task only immediately and asynchronously.
Also
Internally, coroutines and WorkManager work differently. Work manager heavily depends on Android system components like Services, Alarm manager, etc to schedule the work whereas coroutines schedule the work on Worker Threads and also is a language feature unlike WorkManager (API). So it is safe to say that coroutines do not go beyond your application. On the other hand, WorkManager can even execute the given tasks when your application is not active. for instance, background services.
Also as Marko answered, using coroutines will lead to better code readability and quality due to their fundamental design.
I would also like to include ANKO, Its a great library that provides a helpful API around coroutines for Android.
Background tasks fall into one of the following main categories:
Immediate
Deferred
Exact
To categorize a task, answer the following questions:
Does the task need to complete while the user is interacting with the application?
If so, this task should be categorized for immediate execution. If
not, proceed to the second question.
Does the task need to run at an exact time?
If you do need to run a task at an exact time, categorize the task as
exact.
Most tasks don't need to be run at an exact time. Tasks generally allow for slight variations in when they run that are based on conditions such as network availability and remaining battery. Tasks that don't need to be run at an exact time should be categorized as deferred.
Use Kotlin Coroutine when a task needs to execute immediately and if the task will end when the user leaves a certain scope or finishes an interaction.
Use WorkManager when a task needs to execute immediately and need continued processing, even if the user puts the application in the background or the device restarts
Use AlarmManager when a task that needs to be executed at an exact point in time
For more details, visit this link
If your goal is writing clean code without explicitly constructed callbacks you pass to background tasks, then you'll find that coroutines are the only option.
Using coroutines by no means precludes using WorkManager or any other tool for background operations of your choosing. You can adapt the coroutines to any API that provides callbacks as a means to continue the execution with the results of background operations.
From official Documentation:
It is important to note that coroutines is a concurrency framework, whereas WorkManager is a library for persistent work.
WorkManager:
Support for both asynchronous one-off and periodic tasks
Support for constraints such as network conditions, storage space, and charging status
Chaining of complex work requests, including running work in parallel
Output from one work request used as input for the next
Handles API level compatibility back to API level 14(see note)
Works with or without Google Play services
Follows system health best practices
LiveData support to easily display work request state in UI
Waits proper time to run.
Coroutines:
Clean code, works under the hood in a different way. Run immediately.
So depending on your requirements choose the better option.
Has others replied, WorkManager solves a different problem than Kotlin's corountines or a reactive library like RxJava.
WorkManager is now available as beta and additional documentation is produced that hopefully makes this clear.
One of these documents is the blog post I worte with some colleagues: Introducing WorkManager, where you can read:
A common confusion about WorkManager is that it’s for tasks that needs to be run in a “background” thread but don’t need to survive process death. This is not the case. There are other solutions for this use case like Kotlin’s coroutines, ThreadPools, or libraries like RxJava. You can find more information about this use case in the guide to background processing.

Performance comparison: AsyncTasks vs Threads

In my app, I have to call a method which does some heavy work (I can feel device lagging). To avoid this I created an AsyncTask and it works perfectly fine.
I implemented the same thing using a Thread and here, too, it does not give any hiccup and works fine.
Now my question is which one better performance-wise - AsyncTask or Thread.
I know AsyncTask uses a threadpool to perform background tasks but in my case it will be called only once. So I don't think it will create any problems.
Can someone throw some light on it. Which one should I use for better performance?
Note: Both are being called in my Activity e.g. from UI the thread.
Can someone throw some light on it. Which one should I use for better
performance?
I think if you imagine case when you start once native Thread and AsyncTask i think that performance won't differ.
Usually native threads are used in the case if you don't want to inform potential USER with relevant information about progress in some task via UI. Here, native threads fail because they are not synchronized with UI thread and you cannot perform manipulating with UI from them.
On the other hand, AsyncTask combines background work with UI work and offers methods which are synchronized with UI and allow performing UI updates whenever you want via invoking proper methods of its lifecycle.
Generally if some task lasts more than 5 seconds you should inform USER that
"something working on the background, please wait until it will be finished"
For sure, this can be reached with both in different ways but this strongly depends on character of your task - if you need to show progress of task(how much MB is already downloaded, copying number of files and show name of each in progress dialog etc.) or you don't(creating some big data structure in "silent" only with start and end message for instance).
So and at the end of my asnwer:
Which one should I use for better performance?
Completely right answer i think you cannot get because each developer has different experiences, different coding style. How i mentioned, their performance not differ. I think that it's same(if you will read 50 MB file, it won't be faster read neither native thread nor AsyncTask). It depends again on character of task and your personal choice.
Update:
For tasks that can last much longer periods of time, you can try to think also about API tools provided by java.util.concurrent package(ThreadPoolExecutor, FutureTask etc.)
Async tasks are also threads. But they have some utility methods that make it very easy to small background tasks and get back to the UI to make changes to it. The performance would depend on your specific use case. Making absolute statements as to which one is always better would be simplistic and meaningless.
Note that the main advantage of Async tasks over threads is that Async tasks provide helper methods such as onPreExecute(), doInBackground(), onProgressUpdate() and onPostExecute() which make it very easy to perform short background tasks while also interacting with the UI (such as updating a progress bar). These kinds of methods are not available in generic Threads. Basically, Async tasks are threads with UI interaction component built in. Yes, you can use workarounds to try and update the UI from regular threads as well but Async tasks have been specifically built for this purpose and you don't have to deal with Context leaks and so on if you follow it's abstractions.
Async tasks are created to make developers' lives easier.
To sum up:
Async tasks are also threads
Async tasks make it easy to interact with UI while doing short background tasks
Neither is inherently more efficient. It depends on what you want to do.
Good rule of thumb: Use Async tasks if you need to get back to/update the UI after you are done with your background task. Use a regular thread if you don't.
The most common use of Thread are short-term tasks because they need a lot of power and tend to drain the battery and heat the phone up.
And the common use of AsyncTasks are lengthy tasks because of the same battery drain.
But a Thread is far more powerfull, because an AsyncTasks internally uses a Thread itself, but you don't have to configure that much.
ASYNC TASK and Thread do the same thing,
The difference is that you have more control on bare thread and you can benefit from the power of CPU in terms of complex implementation, the velocity of performance depends on your approach on how you implement the threading.
Depending on this article I can say that asynchronous multithreading is the fastest way to perform complex tasks.
https://blog.devgenius.io/multi-threading-vs-asynchronous-programming-what-is-the-difference-3ebfe1179a5
Regarding showing updates to user on UI thread, you can do that by posting on UI from the background thread (check UIhandler and View.Post)

Categories

Resources