
An introduction to libuv - deadwait
http://nikhilm.github.io/uvbook/
======
josephg
I've written a couple of C tools directly on top of libuv[1] to play with it.
I've got to say, its a great little library. Its basically nodejs's entire
cross-platform standard library & event loop exposed to C, without V8 and
without npm. It performs well, the code is pretty high quality and the
internal documentation is excellent. The external API docs aren't very good
though - I found myself reading through nodejs a few times to figure out how I
was expected to use some of the functions.

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](https://github.com/josephg/sharedb)
(Caveat: This was an experiment and libuv has probably changed in incompatible
ways since I wrote this code)

~~~
SpikeGronim
Redis doesn't use libuv, and in fact rejected a patch from MS to add libuv
support. The reason is dependency management, not performance. Redis takes
very very few dependencies - basically just a C compiler and POSIX. This makes
it easier to deploy Redis, and Redis doesn't have to worry about failures in
its non-existent dependencies.

------
jheriko
i am always a bit of jerk about these things because i constantly work with
genuinely performance critical code, but the very first thing puts me off:

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...

~~~
bnoordhuis
Libuv author here. Libuv doesn't try to be all things to all people - its main
users are Node.js and Rust - but if you have suggestions on how to improve the
API or the implementation, please file issues[1] or join us in #libuv on
irc.freenode.org. We welcome outside input.

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.

[1]
[https://github.com/joyent/libuv/issues](https://github.com/joyent/libuv/issues)

~~~
KenoFischer
And Julia! :)

------
kyberias
Is there some introductory text available explaining what is the purpose of
libuv, it's intended usage scenarios etc.?

~~~
ritchiea
It's a C library to handle asynchronous IO. The library it replaced, libev, is
essentially a wrapper around select which is a unix system call that looks for
file descriptors that are ready for reading or writing (for more info you can
use the command 'man select' in bash). My understanding is that select can be
nondeterministic so there were predictability and performance improvements to
be had by replacing it with a better model. The guide also links to this talk
by one of the libuv authors which is a great help in understanding why they
wrote libuv:
[https://www.youtube.com/watch?v=nGn60vDSxQ4](https://www.youtube.com/watch?v=nGn60vDSxQ4)

~~~
jamwt
This is not quite correct. libev is a wrapper around the best available of
select/epoll/kqueue (the same syscalls libuv uses), and it provides nice
timers, thread wake (eventfd/pipe), etc.

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.

~~~
onestone
For the record, Node's I/O performance is better now that it's based on libuv
(after libuv removed its own libev dependency) than when it was based on
libev. This doesn't necessarily mean that libuv is always faster than libev,
but at least for Node's use case it was.

------
the1
[http://redis.io/topics/internals-
rediseventlib](http://redis.io/topics/internals-rediseventlib) ae is good too.

------
malkia
Isn't this example wrong: (I'm not much familiar with libuv, but reading from
the comments it might be):

[http://nikhilm.github.io/uvbook/filesystem.html](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);
           }
       }

~~~
nsm
It's correct. uv_fs_req_cleanup() deletes some private data associated with
the uv_fs_t. `result` is part of the public interface and is unaffected.

------
galapago
It looks like the BeBook.

~~~
nsm
Author here.

It's because it uses the Haiku standard theme shipped with the sphinx
documentation generator, which does come from the Haiku project :)

