Matej Briškár
Matej Briškár

Reputation: 607

How are asynchronous DB libraries implemented?

In general, there is a huge hype around reactive, asynchronous code that asynchronously process requests (play, akka, netty etc.). While executing the code in this way, you are advised to not block and use the asynchronous libraries everywhere possible. If I understand this correctly, this way instead of creating a thread for every request we end up having Thread executors for multiple parts of execution brought by those libraries (main processing of requests, async. calls of services executor, async DB driver executor etc.)

This way execution end up splitted in multiple threads (=in multiple executors). How are these async libraries implemented so that it brings any benefit? Because in scenarion in which the async DB driver has executor that runs a thread that simply waits for DB answer, I don't think it would bring any benefit. We would end up waiting whatsoever and just by creating extra threads to do the wait doesn't help anything. Or does it?

Upvotes: 3

Views: 525

Answers (2)

oshai
oshai

Reputation: 15365

I can tell you from my experience writing https://github.com/jasync-sql/jasync-sql which is an async mysql driver that uses netty under the hood.
First, there is no thread that is blocking when you do an sql query to the database. Instead netty uses an event loop and java nio to have one thread listening on many sockets without blocking.
If you want general info about event loops this is a really good video: https://www.youtube.com/watch?v=8aGhZQkoFbQ

From my understanding, in an ideal application, you will have the number of threads as the number of cores, and they will never block on io, will just do CPU work (computations). So in that ideal world, you will use the ForkJoinPool for everything. In real scenarios, I have never seen application that does it, maybe only super tuned services. Instead, you usually have more threads in some pools, but they usually wait for work and should not block. This still can have very good utilization.

Upvotes: 2

Dan Roberts
Dan Roberts

Reputation: 2329

I think that the common misunderstanding about async libraries comes about because the simplest way to imagine how they work is to think about how you would implement them in the language that the library is written to work with, using the tools available to that language - which generally leads to thinking "if DoWorkAsync has to wait for something else to finish, then surely DoWorkAsync will just be occupying a thread until the work is done". This sounds wasteful and like the only benefit is that the async library deals with managing a thread that will be used for waiting on the work.

However, these async methods actually work with lower level forms of communication than you have direct access to in Java.

When the async work has to deal with some form of IO that it won't be able to immediately get the data from (which includes all sorts of things, such as IPC, disk access and network access - and so, by extensions, database calls) the OS will talk to a device driver that has built-in, low-level support for async calls such that it can start work and then fire some sort of interrupt to tell the OS when the work has completed. During this period, there is no need for the managed thread to continue to exist (and to continue to suck up resources) - while the device driver is dealing with the work, there does not need to be a thread waiting for it. When the device driver indicates that its async work is complete, the OS passes this information up and a thread will be used to continue the work.

The above is a very simplified explanation (and probably inaccurate in all sorts of ways) but hopefully it gets the point across - threads are not required to wait for the async data, which answers your original question.

There is more information in this excellent (and concise) article: There Is No Thread (it's about .net but the same principles apply)

Upvotes: 1

Related Questions