Reputation: 997
I am trying to achieve non IO blocking coroutines (kotlin) in a way that will gain more network calls than threads. It is clear how to use coroutines in a way that doesn't block the main thread, however eventually each coroutine runs within a tread and a network calls blocks that thread (for comparison, using NodeJS allows to reuse the working thread while other requests are waiting for the response to come back).
My use case is that for each incoming request I need to make 2-3 independent external calls, aggregate the response and return. Doing that sequentially is a waste of time. Doing that in parallel will require my service to run about 2-3 times the number of incoming threads (making it about 1K of threads just for waiting for IO).
Many of the couroutine examples are using delay
, and by that allowing to reuse the threads for multiple couroutine concurrently. However by actually using the real live use case of network calling, I cannot achieve that.
What am I missing? How can I suspend the coroutine until the external service responds?
For example, this example runs only on 5 threads, but reuses the threads over the 1000 calls so it all ends within ~100ms (each dealy is 100ms)
val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
(1..1000).forEach {
launch(myPool) {
delay(100)
}
}
}
As opposed to this, that actually runs only 5 concurrent calls over 5 threads, and continue to the next only once is finished. I wish to have all calls executed "in parallel", taking advantage of sending a request while waiting for the response - just as done in NodeJS:
val restTemplate = RestTemplate()
val myPool = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
runBlocking {
(1..1000).forEach {
launch(myPool) {
restTemplate.getForObject("http://myTest.com", String::class.java) // Say it takes 100ms to response
}
}
}
Upvotes: 2
Views: 3804
Reputation: 705
"I wish to have all calls executed "in parallel""!!
Why dont you remove Executors.newFixedThreadPool(5) and give the Dispatchers.IO for coroutine run by his self?
runBlocking {
(1..1000).forEach {
launch(Dispatchers.IO) {
delay(100)
}
}
}
Upvotes: 0
Reputation: 200246
Kotlin coroutines aren't magic that turns your blocking network operations into non-blocking. They only allow you to use an asynchronous networking implementation without the cruft of futures and callbacks.
So, in order to proceed,
Upvotes: 3