ws-tool
ws-tool copied to clipboard
impl Clone for Sender
一般通道的接收都是先反序列化,再根据反序列化的结果再match分发处理,如果Clone了,可能对哪个接收者Receiver会收到消息不一定有直观的预期,所以接收者的对于Clone的需求不太大。
但发送者Sender(代指ws-tool内ws相关的所有发送者)大多数时候都有分享到不同线程的需求。比如说推送通知,就有可能来自于不同系统的推送,也有可能来自其他客户端的推送。如果不能把Sender分享到不同线程的话,实现此类功能就很麻烦。
一般而言会考虑两种方式,一种是通道,一种是加锁: 标准库通道、crossbeam-channel、tokio通道、async-channel,都可以实现Sender的跨线程克隆; 标准库锁、parking_lot、tokio异步锁、fast-async-mutex也都可以克隆;
根据测试,同环境里原则上加锁最快(rustcc论坛里有发过测试结果),所以我试了ws-tool(主要是Frame相关的类型),同步环境下用parking_lot::mutex加锁(我是在ubuntu下测试的,window下可能标准库mutex更快),异步环境下用fast-async-mutex加锁,然后放进一个可分享的map里进行全局调度,可以成功运行。
Sender加锁后在执行send固然能够实现多线程分享,但却不是最佳实践,锁的粒度理论上还能够更细,最好细到write/write_all/write_vectored这个级别,但我看了FrameWriteState::send的源码,发现里面部分的write行为是拆分开来的,在单线程或独占的状态下直接write没问题,但不确定锁的粒度进一步细化后,导致write乱序是否会影响功能实现。
建议:
一、如有必要的话,应把同一个send/async_send里的写行为进行合并;
二、增加一个ShardedSender的类型,内建类型是Arc<Mutex<Sender>>
,普通Sender需要实现Clone/Into变成ShardedSender,ShardedSender克隆还是本类型,但Arc的引用计数为1时,可以into成Sender(不怎么用得到但也算保持类型可逆性)。