can someone please point to me in the kotlinx.coro...
# coroutines
v
can someone please point to me in the kotlinx.coroutines codebase, where the logic is, that a Dispatchers.IO thread will continue on a Dispatchers.Default thread instead of spawning a new one?
t
Copy code
kotlinx.coroutines.scheduling.DefaultScheduler
Looks like what you want. At a casual glance it looks like it pre-allocated the # of threads (caped to 64 or the # of processors you have). Then dispatches to a thread from that pool... or waits until one is available.
actually... I think it just allocates 64 threads, unless you have more than 64 processors... in which case it allocate more ? Which seems weird to me.. but whatever.
k
Why is that weird? A threadpool should generally have at least as many threads as there are cores available on a processor.
t
But it shouldn't have more. At least not for optimizing either throughput or latency. It's easy to control w/ a property... but I'd kinda expected a better default value.
c
It makes perfect sense for an IO-bound thread pool to have more threads than there are cores available. A thread can be blocked by IO (waiting on HDD, a network packet, etc), at which point it’s not using any CPU cycles and it can release the CPU core for other threads while it waits for more bytes to become available. Once more bytes are available, it needs a few more CPU cycles to receive those bytes, then waits again, etc. This article goes into a bit more depth about CPU-bounds vs IO-bound concurrency https://elizarov.medium.com/blocking-threads-suspending-coroutines-d33e11bf4761
t
The whole point of corouties is to de-couple your IO model from your threading model. What this article points out is that if you do that, you don't need more threads than CPUs (my point). If your using threads then you do (also my point).
if your just using co-routines as threads... there is 0 point in them.
a
Not really, IO operations still operate on and block threads, they don't use coroutine suspension. Thus a lot of IO operations can quickly block all your Default threads. You can't decouple IO from threads.
u
Isnt the whole point of coroutine dispatchers, that it does something else when given io coroutine is waiting for some OS socket, database connection, etc? App doesnt own those threads that actually do the work, or is socket actually ran on thread from Dispatchers.io threadpool? Hard to believe that Im not 100% sure, but if app thread actually did the work, then its not "blocked on io" but doing the work and coroutines are pointless
a
There is no magic here, you will still use same
<http://java.io|java.io>.*
API for IO operations in Kotlin and it is blocking. There is
java.nio.*
API, but I don’t think it is widely used yet. For example on Android nio files are supported only starting from SDK 26.
u
which means you have to "sacrifice" a thread to java file io, even if it actually does nothing, just sits on some lock, right? In which case coroutines help nothing, you'll instantiate 20 threads for 20 files
a
Yes, but you don’t have to sacrifice it forever, it will be eventually unblocked and returned to a thread pool. This is why you’d want a larger
<http://Dispatchers.IO|Dispatchers.IO>
pool instead of
Dispatchers.Default
.
u
right, but wouldnt you then use Disp.Default for java nio? (If Disp.IO is just meant for this sacrifition to old java basically, not io in general) In other words, would you use Dispatchers.IO for an async api?
a
I’d say
Dispatchers.Default
makes sense in this case, as it will (probably) be a CPU intensive task which can be bound to CPU cores. But I have little knowledge of Java NIO, sorry.
u
Doesnt have to be nio. Just in general. Any async api will have its own threadpool i presume (okhttp does etc)
a
If you use callbacks then there is no need to specify a dispatcher at all, when converted into a suspending function it will just use your current dispatcher to resume (e.g.
Dispatcher.Main
).
u
Makes sense. Im just lamenting why would anyone use DIspatcher.io for anything other than wrapping legacy (java) apis which "hijack" your thread In which case kotlin renaming it to Dispatcher.default makes much more sense than rx calling it Schedulers.computation()
a
In case of 3rd party libraries (OkHttp, Room, etc) you can rely on main-safety principle, which means that the suspending function will make sure to not block by using a correct dispatcher or custom thread pool itself. So yes, I’d say you only need
<http://Dispatchers.IO|Dispatchers.IO>
when working with IO directly, e.g. reading from files, etc.
👍 1