[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)