Hacker News new | ask | show | jobs
by singron 360 days ago
After a brief skim, it looks like this implementation is highly optimized for throughput and broadcasts whereas a channel has many other usecases.

Consumers subscribing to the same event type are placed in a group. There is a single lock for the whole group. When publishing, the lock is taken once and the event is replicated to each consumer's queue. Consumers take the lock and swap their entire queue buffer, which lets them consume up to 128 events per lock/unlock.

Since channels each have a lock and only take 1 element at a time, they would require a lot more locking and unlocking.

There is also some frequent polling to maintain group metadata, so this could be less ideal in low volume workloads where you want CPU to go to 0%.

2 comments

Seems that the trick would be detecting if there is a queue building up and dispatching multiple events per lock if so. Double buffering is a common enough solution here. The reader gets one buffer to write to and the writer gets another, and when the read buffer is drained the write buffer is swapped.

For low traffic messages you need only send one message at a time, but if the receiver slows down the sender can avoid resorting to back pressure until the buffer is more than half full.

I wonder if a broadcast could be implemented as a specialization of a ring buffer:

Use 1 ring buffer, and N read pointers. The writer determines how far it can write by taking the minimum of the read pointers. ... I think that's all you'd need? The writer will block if a reader is too slow, but any broadcast that preserves messages and has bounded memory will have that problem. Maybe the difficulties will be in adding and removing readers.