top | item 46291655

(no title)

qbane | 2 months ago

By a quick glance, yes, this is what I want: a channel to communicate between processes via a piece of shared memory, protected by a pair of futexes.

In JS ecosystem, buffers that allow data loss is more common (aka ring buffers), but ringbuf.js [1] is the only complete implementation to my knowledge. In my use case on I/O between WASM modules where data must be transferred as-is, the process must block on buffer overrun/underrun in a synchronous manner. Therefore a circular buffer is required. I could not find such a niche library written in JS, so I decided to bite the bullet and reinvent the wheel [2].

[1]: https://github.com/padenot/ringbuf.js

[2]: https://github.com/andy0130tw/spsc

discuss

order

xavierxwang|2 months ago

After a quick glance, it seems that you don’t maintain the reading/writing status in the shared memory. That means you have to make a syacall in every read/write call. You could look into the kaze-core for an alternative implementation, which doesn’t require any syscall if possible.

Btw, kaze-core uses a `used` atomic variable, to avoid reading both readPos/writePos in routine - they are not atomic at all.

qbane|2 months ago

That is a fair assessment. Maintaining read/write pos and peek them at every operation is a big performance hit. The impact is amplified if each invocation needs a syscall. That is exactly what futexes address: Allowing spin locks to remain in user space and avoid entering the kernel as long as contention is low.

In JavaScript, atomic operations are relatively lightweight, so their overhead is likely acceptable. Given that, I am open to adjusting my code to your suggested approach and seeing how it performs in practice.