I'm quite curious to see how much performance you lose through libuv compared to using the lower level IO primitives directly (epoll, select and friends). I know redis doesn't use any high level event libraries, but I haven't seen any benchmarks.
[1] https://github.com/josephg/sharedb (Caveat: This was an experiment and libuv has probably changed in incompatible ways since I wrote this code)
uv_loop_t* loop = uv_loop_new();
does the compiler know where this exists, is it allocated on demand, is there a lock involved? i hope to get the good answers to these questions but the naming of the function alone makes me skeptical. this skepticism turns out to be justified.
digging in:
loop = (uv_loop_t* )malloc(sizeof(uv_loop_t));
so the answers to all of my questions are the wrong ones for me. i might override the allocator to be less rubbish in my context. but simple things like this tell me that this library was not architected for the kinds of performance considerations that i need to make.
at this high level its not so important, but the more digging i do the 'worse' it gets...
generally this does look helpful, but it gives me nothing over my existing solutions (in my context) which, for example, require zero run-time memory allocations - outside of OS level API calls that I have zero control over - and lean heavily towards lockless implementations, avoiding the massively (but understandably) heavyweight OS provided threading primitives...
thread safety of malloc and other standard library (i.e. libc) type stuff is, in reality, up to the implementor. even when things have no requirement to be thread safe implementors (Microsoft) will often insert what i call 'sledgehammer thread safety' to protect bad programmers from themselves. i can understand why, but it prevents me from being able to use these libraries.
when i can do a better job than your standard library, you have failed imo. but it is just my opinion...
As a bit of history, the reason why uv_loop_new() mallocs memory for the struct (and it's something of an anomaly in that respect, most other API functions don't) is that the thing that came before libuv, libev, worked like that. It's something we can change if there is demand for it.
tbh, i was angling for 'my criticism isn't great because i am a specialist in a specialist field'.
(also, it does look like a genuinely useful library for most use cases - im just lazy and want everyone else to do my job for me :P)
What it doesn't provide that libuv does is high-level support for asynchronous filesystem I/O, a built-in asynchronous DNS resolver, process management abstractions and more high-level cross platform goodies for writing asynchronous apps. libev also doesn't have very good support on windows.
So, the main improvements provided by libuv are a more extensive high-level API and good windows support. I doubt speed (or deterministic latency or scalability.. etc) was a goal, as libev is very, very fast. Just lower-level.
https://github.com/joyent/libuv/wiki/Projects-that-use-libuv
I'm very familiar with Twisted, Perl AnyEvent, and Gevent/Greenlet -- libuv seems to be like that.
http://nikhilm.github.io/uvbook/filesystem.html
void on_read(uv_fs_t *req) {
uv_fs_req_cleanup(req); // <-- bug? freeing here, later using req ptr?
if (req->result < 0) {
fprintf(stderr, "Read error: %s\n", uv_strerror(uv_last_error(uv_default_loop())));
}
else if (req->result == 0) {
uv_fs_t close_req;
// synchronous
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
}
else {
uv_fs_write(uv_default_loop(), &write_req, 1, buffer, req->result, -1, on_write);
}
}It's because it uses the Haiku standard theme shipped with the sphinx documentation generator, which does come from the Haiku project :)