Delayed construction.
jjl opened this issue · 3 comments
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 heapunbounded::<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 :)
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 Event
s and their listeners. The problem here is that notifying would initialize Event
s, which is pretty expensive. But there's no point in initializing when notifying! If Event
is uninitialized when notified, that means there are no EventListener
s to notify. :)
Updating to event-listener
v2.3.1 brings construction of a channel from ~1000ns to ~250ns on my 2020 macbook pro.