Nonblocking-io vs blocking-io when transferring raw data

The apache HTTPComponent document has a statement:

Contrary to popular belief, NIO performance in terms of raw data performance is significantly lower than I / O blocking performance.

It's true? Can someone explain this in more detail? And what is a typical use case when

request / response processing should be decoupled

+7
source share
2 answers

Non-blocking IO should be used when you can process a request, send it for processing in a different execution context (another thread, an RPC call to another server, some other asynchronization mechanism) and free the web server thread to process more incoming requests. When the response processing is completed, the response processing thread will be called and it will send the response to the client.

I would recommend reading non-standard documentation for a better understanding of the concept.

As for higher throughput: when your server sends / receives large amounts of data, all of these context switches and transferring data between streams can really hurt overall performance. Think of it this way: you get a large request (a PUT request with a large file). All you have to do is save it to disk and return OK. Starting to throw it between threads can lead to several more mem-copy operations that would be necessary if you just threw them to disk in the same thread. And processing this operation in the async method will not improve performance: although you could free the request processing thread back to the web server thread pool and allow it to process other requests, the main performance bottleneck is your IO drive, in which case an attempt is made to save more files at the same time, it will only slow down.

I hope I was clear enough. Please feel free to ask more questions in the comments if you need more explanation.

+2
source

The first statement is true only when the number of parallel queries is relatively small (or rather tens of thousands). It's all about using multiple threads (blocking) instead of one or more threads (non-blocking). Let's say you want to write an application that downloads only a file from a remote server. If your application needs to download only one file at a time, you only need one stream. But if you have a crawler that runs thousands of HTTP requests, you need to have thousands of streams (or use a limited number of streams + NIO instead). For so many threads, the problem is context switching, which can significantly slow down your application (therefore, NIO is better for this number of concurrent requests).

But back to your question. Why can NIO be slower in terms of raw data performance? The reason is that CPU time is used by NIO-driven applications. For such a case, in the blocking model, your code performs only one thing - waiting for data (it performs the recv () operation in a loop). In a NIO application, the logic is much more complicated: in a loop, the code uses a selector to select a set of keys (which includes the epoll_wait system call on Linux, Oracle JVM), then iterates over the set, selects a channel for each key, and then reads data from the channel (reading () in OS). In the standard locking model, all you do is execute the recv () system function. Bottom line: an NIO-driven application in this case uses more CPU time and generates more mode-switching operations due to more system calls (speaking of mode switching, I mean switching from user mode to kernel mode). Therefore, the time required to download the file will be higher.

+3
source

All Articles