smol-rs/async-channel

Delayed construction.

jjl opened this issue · 3 comments

jjl commented

Hello, how's it going?

I've been doing some benchmarking today to figure out where i can improve the performance of async_backplane (which is pretty cool btw, take a look :) ) and the bulk of the time is spent in channel creation/destruction (i presume creation). Is there any way some of this work could be delayed?

On my crappy 2015 macbook pro, it's ~1.3us to create and drop, which seems a little steep vs the ~180ns for try_send + try_recv. I realise there are two ends of it so it may not be entirely possible, but I thought I'd ask :)

That is certainly a little steep, I would expect 5x smaller numbers... If you're never actually using channels that's a big price to pay just for channel construction + destruction. Anyways, regarding channel construction:

  • bounded::<T>(n) allocates something like [(T, usize); n] on the heap
  • unbounded::<T>() allocates something like [(T, usize; 32] on the heap

I think those allocations could certainly be delayed, it'd just be a bit of work :)

jjl commented

For comparison, a ConcurrentQueue is ~200ns to create and destroy on the same box, so I was a bit surprised by this. I'll take a look at some point, but it's pretty low priority right now.

Turns out this was an issue in event-listener: smol-rs/event-listener@3142ee7

Event has a built-in mechanism for delayed construction. However, when Sender or Receiver is dropped, the channel becomes closed. Closing notifies all Events and their listeners. The problem here is that notifying would initialize Events, which is pretty expensive. But there's no point in initializing when notifying! If Event is uninitialized when notified, that means there are no EventListeners to notify. :)

Updating to event-listener v2.3.1 brings construction of a channel from ~1000ns to ~250ns on my 2020 macbook pro.