[HN Gopher] libxev: A cross-platform, high-performance event loop
       ___________________________________________________________________
        
       libxev: A cross-platform, high-performance event loop
        
       Author : tosh
       Score  : 132 points
       Date   : 2024-04-17 15:11 UTC (7 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | asveikau wrote:
       | This is the first I've heard kqueue described as a macOS thing.
       | It's from FreeBSD.
       | 
       | Yes it exists on macOS. My experience with it is that it's
       | slightly different and quirky on each BSD.
        
         | CharlesW wrote:
         | Yep, macOS leverages a bunch of technologies and tools that
         | originated in FreeBSD.
        
         | mitchellh wrote:
         | Hi, this is my project.
         | 
         | The README only states that I use kqueue on macOS, but I don't
         | claim it is specific or originated from macOS. I've read the
         | README over a few times and can't find where you'd get the
         | feeling that it's a macOS-only thing. If I can edit it in any
         | way to make that clearer let me know.
         | 
         | libxev is not compatible with BSD currently because macOS's
         | kqueue API is very slightly different from BSDs to make it
         | incompatible (i.e. I use mach ports a lot on macOS, but other
         | parts of the syscall interface also vary slightly).
        
           | asveikau wrote:
           | If you depend heavily on Mach ports I don't think "kqueue
           | (macOS)" is an accurate description. That makes it sound like
           | it has more of a chance to work on BSD than it does.
        
             | mitchellh wrote:
             | It is an accurate description. The mach ports are waited on
             | through kqueue, and I use kqueue for all other waiters with
             | "standard" fds (i.e. files). But my usage of mach ports
             | (even for a partial use case) make it incompatible with
             | BSD, and even if I didn't use mach ports the kqueue
             | structures used by macOS are slightly different and
             | incompatible anyways, and I don't claim BSD support
             | anywhere.
             | 
             | It's splitting hairs and being a bit pedantic, but you also
             | reordered my descriptions: in the README I always say
             | "macOS (kqueue)" and not the reverse which you incorrectly
             | quoted. I think that makes a small but tangible difference.
        
               | asveikau wrote:
               | I did misread and misquote that. But when a remark is
               | parenthetical I guess I consider them equivalent. macOS
               | and kqueue is not equivalent. Maybe macOS (using kqueue
               | and Mach ports) would make it clearer?
        
       | jpgvm wrote:
       | Completion based cross-platform I/O? Sign me up.
        
       | dsp_person wrote:
       | Can this be used to make something that feels like Qt's signals
       | and slots?
        
       | gigatexal wrote:
       | on MacOS are kqueue and libdispatch/grand central dispatch doing
       | different things?
        
         | 0x457 wrote:
         | libdispatch/GCD is a task scheduler built on top of kqueue.
         | It's meant for moving things away from the main UI thread
         | without thinking how often you do that.
        
           | gigatexal wrote:
           | Thanks for clarifying!
        
       | mitchellh wrote:
       | This is my project.
       | 
       | I use it as the core cross-platform event loop layer for my
       | terminal (https://mitchellh.com/ghostty). I still consider libxev
       | an early, unstable project but the terminal has been in use by
       | hundreds to now over a thousand beta testers daily for over a
       | year now so at least for that use case its very stable. :) I know
       | of others using it in production shipped software, but use it at
       | your own risk.
       | 
       | As background, my terminal previously used libuv (the Node.js
       | core event loop library), and I think libuv is a great project! I
       | still have those Zig bindings available (archived) if anyone is
       | interested: https://github.com/mitchellh/zig-libuv
       | 
       | The main issue I had personally with libuv was that I was
       | noticing performance jitter due to heap allocations. libxev's
       | main design goal was to be allocation-free, and it is. The caller
       | is responsible for allocating all the memory libxev needs
       | (however it decides to do that!) and passing it to libxev. There
       | were some additional things I wanted: more direct access to mach
       | ports on macOS, io_uring on Linux (although I think libuv can use
       | io_uring now), etc. But more carefully controlling memory
       | allocation was the big one.
       | 
       | And it worked! Under heavy IO load in my terminal project, p90
       | performance roughly matched libuv but my p99 performance was
       | much, much better. Like, 10x or more better. I don't have those
       | numbers in front of me anymore to back that up and my terminal
       | project hasn't built with libuv in a very long time. But I
       | consider the project a success for my use case.
       | 
       | You're probably better off using libuv (i.e. the Node loop, not
       | my project) for your own project. But, the main takeaway I'd give
       | people is: don't be afraid to reimplement this kind of stuff for
       | you. A purpose-built event loop isn't that complicated, and if
       | your software isn't even cross-platform, it's really not
       | complicated.
        
         | ajoseps wrote:
         | I saw ghostty and thought, "isn't that the terminal written by
         | the guy who cofounded hashicorp?". I really enjoy your ghostty
         | blog posts and will be checking out libxev!
        
         | samsquire wrote:
         | Thank for you for sharing.
         | 
         | What do you think are the next steps for a next generation
         | event loop?
         | 
         | I've been experimenting with barriers/phasers, LMAX Disruptors
         | and my own lock free algorithms.
         | 
         | I think some form of multithreaded structured concurrency with
         | coroutines and io_uring.
         | 
         | I've been experimenting with decoupling the making sending and
         | recv independently parallel with multiple io_urings "split
         | parallel io" - so you can process incoming traffic separately
         | from the stream that generates data to send. Generating sends
         | is unblocked by receive parsing and vice versa.
         | 
         | Interested in seastar and reactors.
        
           | password4321 wrote:
           | https://en.wikipedia.org/wiki/Data_Plane_Development_Kit
        
         | adonese wrote:
         | (Off topic) but any chance you might include me in the ghostty
         | private testers? (adonese@nil.sd)
        
         | mattgreenrocks wrote:
         | Very nice! TBH, libuv sometimes felt like it is popular because
         | it's popular rather than sheer technical prowess. I was never
         | comfortable with how much allocation is done by it, and I don't
         | always find how it deals with platform primitives as useful as
         | I'd like.
         | 
         | > don't be afraid to reimplement this kind of stuff for you. A
         | purpose-built event loop isn't that complicated,
         | 
         | Amen. There's no need to view the event loop as mysterious.
         | It's just a while loop that is constantly coordinating IO.
        
         | password4321 wrote:
         | > _libxev 's main design goal was to be allocation-free_
         | 
         | Maybe "allocation-free" should be in the GitHub project
         | description instead of or in addition to "high performance".
        
       | jauntywundrkind wrote:
       | io_uring support is obviously great & excellent, fulfills the
       | "high performance" part well. brought an immediately smile to my
       | face.
       | 
       | i was _not_ expecting  "Wasm + WASI" support at all. that's very
       | cool. implementation is wasi_poll.zig (https://github.com/mitchel
       | lh/libxev/blob/main/src/backend/wa...). not to be unkind, but
       | this makes me wonder very much if WASI is already missing the
       | mark, if polling is the solution offered.
       | 
       | gotta say, this is some very understandable clean code. further
       | enhancing my sense that i really ought be playing with zig.
        
       | Jarred wrote:
       | We copied libxev's code for the timer heap implementation in Bun
       | for setTimeout & setInterval, and it was a ~6x throughput
       | improvement[0] on Linux compared to our previous implementation.
       | 
       | [0]: https://twitter.com/jarredsumner/status/1736741811039899871
        
         | hinkley wrote:
         | Why do you suppose node is still 50% faster on this benchmark?
         | v8 trickery or something in the library differences?
        
           | Jarred wrote:
           | The timer heap currently lives on a different thread instead
           | of the main thread, which means timers have to be allocated
           | and scheduled separately for each one. Scheduling things to
           | other threads is expensive. The reason it works this way
           | isn't good and we will fix it but haven't prioritized it yet
        
       | hinkley wrote:
       | I was going to say, "I wonder if Bun.js would/could use this" but
       | it looks like Jarred Sumner has been cherry-picking bits of
       | libxev for at least six months.
        
       | eqvinox wrote:
       | As someone maintaining a project with its own event loop: don't
       | do it in larger projects.
       | 
       | The problem is that you'll start having dependencies on external
       | libraries. And when those then need event loop integration,
       | things get messy. We've introduced bugs before, caused by subtle
       | differences in semantics. (Like: does write imply read? Are
       | events disarmed while running? What about errors?)
       | 
       | If the lib and event loop are reasonably popular, someone else
       | probably has integrated them before. Or the lib supports the
       | event loop natively (or uses libverto.) Either saves you some
       | trouble.
       | 
       | Also: please add libverto support for your event loop :)
       | https://github.com/latchset/libverto
        
       ___________________________________________________________________
       (page generated 2024-04-17 23:00 UTC)