Remix.run Logo
nananana9 6 hours ago

Yes, command buffers over shared memory are the correct way to do this.

  1. You don't need to convert your discrete messages into a stream with size metadata, only for them to immediately be converted to a message on the other side.
  2. You don't need to jump into the kernel to copy over 20 bytes, only for the other side to jump into the kernel to copy it back.
  3. You don't need to deal with the "oh but what if my read returns half a message because this is a stream"
  4. You don't need to pretend you're doing network programming.
Regardless, it's not that big of a deal - this is like my 73th biggest gripe with Wayland, I only mentioned it since GP was talking about network transparency.

It's pretty representative of the project though - "We're doing things the way we've always done them, but slightly different. Now rewrite all your software to work with our thing. No, you cannot do global keyboard shortcuts or set window position. You don't like it? We're doing this for free, you cannot critique it."

mort96 6 hours ago | parent | next [-]

You don’t have to hit the kernel for 20 bytes. Buffer up all your commands and send them to the kernel with a single write(). The other side can then read them all (or however many fit in its receive buffer) with a single read(). The only real difference is that the memcpy happens in the kernel instead of the receiver and that the kernel provides a useful blocking mechanism by default so you don’t have to manage that in userspace code.

You need some kind of serialisation either way. It can be as simple as “this message has the shape of this C struct”, but that’s the case whether you’re talking shared memory command buffers or sending data over a socket (and there are good arguments for and against in both cases).

You’re right that you don’t need to deal with “oh I received half a message” when using shared memory command buffers, but that’s more a code complexity thing someone solves once in wayland-client and then nobody has to really think about it again. It’s not really a performance concern (because hopefully the rx buffer is large enough for it to happen rarely) or application code complexity concern.

nananana9 6 hours ago | parent [-]

Sure. But imagine some piece of exotic hardware, e.g. computer mouse, that reports its movement at 1000Hz.

If the compositor wants to notify the client as soon as possible, it has to send 1000 messages per second. If you buffer them, you're wasting the hardware's potential, if you don't buffer, them you're doing 1000 write()s per second, which is... ugh.

If you're literally going to design the protocol from scratch and require all existing software to deal with it, why not pick the IPC model that doesn't have this issue.

mort96 6 hours ago | parent | next [-]

Wait how do you solve that with shared memory command buffers? Don’t you need to involve the kernel to notify the receiver that you’ve written stuff to the command buffer?

Or would the receiver spin in a tight loop on a memory load from some byte in shared memory which indicates a new buffer is submitted, so that it gets notified without involving the kernel? Or is there some fancy mechanism I’m not aware of?

nananana9 6 hours ago | parent [-]

You most likely already have a tight loop lying around - the compositor needs to composite the screen each frame, you can probably poll in there. The client likely has one too, if not, you can involve the kernel & scheduler. If you need super high precision you probably busy wait, I don't know what the Linux scheduler's resolution is.

I would probably expose a poll() and let the client deal with it, I don't know if there's a one-size-fits-all signaling mechanism. But you have control over it, which is probably another plus.

mort96 6 hours ago | parent [-]

Those loops aren’t tight, they sleep for like 10-16ms for live windows or much longer for background windows. You were talking about receiving updates at 1000Hz.

simonask 4 hours ago | parent | prev | next [-]

Just to let you know, 1000 messages per second over a UNIX socket between two processes is very much well within the capabilities of any recent machine running, say, Linux. That’s not many at all.

simoncion 5 hours ago | parent | prev [-]

> But imagine some piece of exotic hardware, e.g. computer mouse, that reports its movement at 1000Hz.

Speaking of... it looks like common Wayland compositors [0] still kill clients that can't keep up with "high speed" event generators like 1kHz mice. [1] So, that's nice.

(For people who plan to retort with "just handle events in a timely manner", check out the comment here [2]. OSX, Windows, and X11 all cope just fine with programs that go unresponsive for multiple seconds. If the statements in this bug report (and the reports I've read elsewhere) are accurate, Wayland doesn't... and that is inexcusable.)

[0] ...or whatever the Wayland terminology is for the thing that does the work of the X11 compositor + window manager...

[1] <https://gitlab.freedesktop.org/wayland/wayland/-/work_items/...>

[2] <https://gitlab.freedesktop.org/wayland/wayland/-/work_items/...>

asdfaoeu 6 hours ago | parent | prev [-]

You would have a lot of security issues right? Whether or not it's useful Wayland does prevent to isolate clients from each other.

mort96 6 hours ago | parent | next [-]

They’re right on this one, shared memory isn’t some scary dangerous thing. Both processes will just have some region of their respective virtual address space which are mapped to the same physical memory, which they can use to share data. Wayland already uses this for pixel data.

nananana9 6 hours ago | parent | prev [-]

Not really, you can have one command buffer per client or process, and map each one in the virtual space of the process that's supposed to write to it.