6 ms·
Trick is that nginx uses thread pools for non-blocking reading on the "fast" devices - you can't use coroutines/fibers, because on Linux is not reliably possibl
by nemanjaboric 9y ago
Trick is that nginx uses thread pools for non-blocking reading on the "fast" devices - you can't use coroutines/fibers, because on Linux is not reliably possible to read the regular file in a non-blocking way, as far as I'm aware, so that means that `read` in a single fiber would block entire thread until the data is fetched from the disk.
In the storage engine I'm developing/maintaining, I've been using fibers, for both network and disk IO, until people started noticing that, if number of the client grows, and if they ask a lot of data (generating a lot of disk traffic), the performance drops severely. I've moved to the thread pools, dispatching my disk IO operations there (although it's much problematic for the reads, as writes would be performed by kernel anyway, `fsync` and `close` would be operations that you still want to do in the separate thread): https://github.com/sociomantic-tsunami/dlsnode/blob/master/src/dlsnode/util/aio/AsyncIO.d https://github.com/sociomantic-tsunami/dlsnode/blob/master/s...
edit: used right link for the freshly opensourced repo.
- vbezhenar 9y agoWhy files can't be read without blocking with Linux? There's certainly an API for this.
- signa11 9y ago> Why files can't be read without blocking with Linux? There's certainly an API for this. i guess you are referring to aio(7) ? posix aio on linux is implemented in glibc, and doesn't scale in presence of multiple threads. which is probably what is alluded to...
- nemanjaboric 9y agoWhich API are you referring to? If you're referring to `aio_` that's just glibc's user-space thread-pool emulation of the POSIX's asynchronous IO + many operations needed for the truly async IO are not supported (such as `stat` and `open`). There's `io_` syscalls family, but that's not in the ready-to-use state yet, judging by the manpages and various patches being submitted every month.
- vbezhenar 9y agoI'm referring to `fcntl(fd, F_SETFL, flags | O_NONBLOCK)`. `stat`, `open` are blocking, yes, didn't think about that. Also according to [1] file operations will always block, even in non-blocking mode, so I was wrong, sorry. 1: https://www.remlab.net/op/nonblock.shtml https://www.remlab.net/op/nonblock.shtml
- signa11 9y ago> ... Also according to [1] file operations will always block ... not quite :) look at aio(7)
- biokoda 9y agoio_ syscalls only really work on XFS and require O_DIRECT which means kernel is not caching anything. Unsuitable for web servers.
- deleted 9y ago[deleted]
- zbobet2012 9y agoYou can move the the co-routine onto another thread. The go scheduler does this: https://morsmachine.dk/go-scheduler https://morsmachine.dk/go-scheduler There isn't really a "comparison" here. Co-routines/fibers could behave exactly like nginx does for IO or not at all. It all depends on the implementation.
- nemanjaboric 9y agoYes, sorry, I've missed the point that you can move them across the threads (was sidetracked by the usual notion of them running in the same thread).
- srean 9y agoA slightly off-topic question tinged with a touch of envy that you get to work on D. Many HN readers are apprehensive of the use of D because it is garbage collected and conjecture that it is not appropriate for low latency and/or high throughput work loads. Correct me if I am wrong, but that is exactly the kind of load the sociomantic needs to address. I have thoroughly enjoyed the relevant Dconf videos but it would be great to hear some first hand account. BTW is the move to D2 done ?
- nemanjaboric 9y agoOh, I'm aware this is a late reply, but it's better than nothing. Yes, what you describe is exactly the kind of load we're addressing, and we're not getting GC to be in the way, simply by making usage of the reusable memory buffers, which are allocated in the first few requests, and then always reuse/recycled & fetched from the pool, so that we're not giving a chance for GC to kick in (as explained in the great blog post series, in D, GC mark&sweep will kick in only on allocations, completely deterministic: https://dlang.org/blog/category/gc/ https://dlang.org/blog/category/gc/). Ocean provides some help here: https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src/ocean/core/Buffer.d https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src... https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src/ocean/util/container/pool/FreeList.d https://github.com/sociomantic-tsunami/ocean/blob/v2.x.x/src..., etc. This makes D completely suitable for these kinds of applications, and from my experience, none of D's features or the misfeatures is making such implementations hard. D2 move is not yet completely done. We're still writing code that's compatible in both D1 and D2. For example, DHT node project (https://github.com/sociomantic-tsunami/dhtnode https://github.com/sociomantic-tsunami/dhtnode) and libraries on which it's depending on such as ocean (https://github.com/sociomantic-tsunami/ocean https://github.com/sociomantic-tsunami/ocean) and swarm (https://github.com/sociomantic-tsunami/swarm https://github.com/sociomantic-tsunami/swarm) are able to run in D2 with no performance penalties, but they still don't use D2-only constructs.
- srean 9y agoAppreciate your reply and welcome to HN.