Currently all reads and writes on all channels share a Mutex onto a UdxSocket. This leads to high congestion and sub-par performance, especially with many channels (UdxStreams).
The solution is to use a lock-free design. Options are:
Channels (e.g. from async-channel) - this means, at least for writing, that we'd have to allocate additional buffers. For reading it might work to send Packets over the channel without allocating, and send back a read cursor which ticks garbage collection for read packets.
- An async pipe like
tokio::io::DuplexStream or sluice::pipe::Pipe. I have tried an implementation based on these, but have not succeeded because the types are not Clone, and wrapping them into a Mutex is not easy either, because the impl of AsyncBufRead (which we want if we don't want to allocate on each write) contains a reference to the pipe, which prohibits mutable access to self while holding onto the read buffer.
Either of those can work out likely with some more thought about alias and lifetime rules.
Currently all reads and writes on all channels share a Mutex onto a
UdxSocket. This leads to high congestion and sub-par performance, especially with many channels (UdxStreams).The solution is to use a lock-free design. Options are:
Channels (e.g. fromasync-channel) - this means, at least for writing, that we'd have to allocate additional buffers. For reading it might work to sendPackets over the channel without allocating, and send back a read cursor which ticks garbage collection for read packets.tokio::io::DuplexStreamorsluice::pipe::Pipe. I have tried an implementation based on these, but have not succeeded because the types are notClone, and wrapping them into aMutexis not easy either, because the impl ofAsyncBufRead(which we want if we don't want to allocate on each write) contains a reference to the pipe, which prohibits mutable access to self while holding onto the read buffer.Either of those can work out likely with some more thought about alias and lifetime rules.