Muhammad Talha

04/30/2022, 6:10 PM
Hey all, I'm looking for some help to understand blocking calls within a coroutine. I was looking at an example for Ktor which uses a coroutine to do a blocking db call. Initially I was wondering why the db call needs to be in another coroutine. Since the route handler function is already in a coroutine, I thought it didn't need to be. Now I'm thinking it in fact does because there are limited number of potential threads (I know coroutine and threads don't map 1:1) and we don't want to block even this coroutine because it can potentially be reused to process another request. Is my understanding correct? More generally, is it the case that any time I want to do any time consuming operation, that I should create a new coroutine regardless if I'm already in a coroutine? This is because although there may be other threads available to process information at some point there will be none available and everything will be blocked?

Zach Klippenstein (he/him) [MOD]

05/10/2022, 2:46 PM
Operations that block on IO should be done not just in a different coroutine, but specifically on a dispatcher intended to handle IO operations, such as Dispatchers.IO. Those dispatchers typically have a higher thread limit since the threads aren't expected to do CPU-bound work and rather just spend most of their time sleeping, waiting for the OS to call them back. Meanwhile, CPU-bound dispatchers like Dispatchers.Default are limited to the number of available cores because they're expected to always be using the processor and so having more threads than cores wouldn't make sense. So if you do blocking IO on such a dispatcher, you're keeping an entire core unuseable for no reason.

Muhammad Talha

05/10/2022, 3:18 PM