Skip to content

Commit 581d80d

Browse files
committed
perf(fake-tcp) use flume to avoid locking in receiver, improved single
connection performance by 300%
1 parent 55da4d6 commit 581d80d

2 files changed

Lines changed: 17 additions & 17 deletions

File tree

fake-tcp/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ rand = { version = "0.8", features = ["small_rng"] }
2222
log = "0.4"
2323
internet-checksum = "0.2"
2424
tokio-tun = "0.5"
25+
flume = "0.10"

fake-tcp/src/lib.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ use std::net::{Ipv4Addr, SocketAddrV4};
5353
use std::sync::atomic::{AtomicU32, Ordering};
5454
use std::sync::{Arc, RwLock};
5555
use tokio::sync::broadcast;
56-
use tokio::sync::mpsc::{self, Receiver, Sender};
57-
use tokio::sync::Mutex as AsyncMutex;
56+
use tokio::sync::mpsc;
5857
use tokio::time;
5958
use tokio_tun::Tun;
6059

6160
const TIMEOUT: time::Duration = time::Duration::from_secs(1);
6261
const RETRIES: usize = 6;
63-
const MPSC_BUFFER_LEN: usize = 512;
62+
const MPMC_BUFFER_LEN: usize = 512;
63+
const MPSC_BUFFER_LEN: usize = 128;
6464
const MAX_UNACKED_LEN: u32 = 128 * 1024 * 1024; // 128MB
6565

6666
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
@@ -79,17 +79,17 @@ impl AddrTuple {
7979
}
8080

8181
struct Shared {
82-
tuples: RwLock<HashMap<AddrTuple, Sender<Bytes>>>,
82+
tuples: RwLock<HashMap<AddrTuple, flume::Sender<Bytes>>>,
8383
listening: RwLock<HashSet<u16>>,
8484
tun: Vec<Arc<Tun>>,
85-
ready: Sender<Socket>,
85+
ready: mpsc::Sender<Socket>,
8686
tuples_purge: broadcast::Sender<AddrTuple>,
8787
}
8888

8989
pub struct Stack {
9090
shared: Arc<Shared>,
9191
local_ip: Ipv4Addr,
92-
ready: Receiver<Socket>,
92+
ready: mpsc::Receiver<Socket>,
9393
}
9494

9595
pub enum State {
@@ -102,7 +102,7 @@ pub enum State {
102102
pub struct Socket {
103103
shared: Arc<Shared>,
104104
tun: Arc<Tun>,
105-
incoming: AsyncMutex<Receiver<Bytes>>,
105+
incoming: flume::Receiver<Bytes>,
106106
local_addr: SocketAddrV4,
107107
remote_addr: SocketAddrV4,
108108
seq: AtomicU32,
@@ -126,14 +126,14 @@ impl Socket {
126126
remote_addr: SocketAddrV4,
127127
ack: Option<u32>,
128128
state: State,
129-
) -> (Socket, Sender<Bytes>) {
130-
let (incoming_tx, incoming_rx) = mpsc::channel(MPSC_BUFFER_LEN);
129+
) -> (Socket, flume::Sender<Bytes>) {
130+
let (incoming_tx, incoming_rx) = flume::bounded(MPMC_BUFFER_LEN);
131131

132132
(
133133
Socket {
134134
shared,
135135
tun,
136-
incoming: AsyncMutex::new(incoming_rx),
136+
incoming: incoming_rx,
137137
local_addr,
138138
remote_addr,
139139
seq: AtomicU32::new(0),
@@ -187,8 +187,7 @@ impl Socket {
187187
pub async fn recv(&self, buf: &mut [u8]) -> Option<usize> {
188188
match self.state {
189189
State::Established => {
190-
let mut incoming = self.incoming.lock().await;
191-
incoming.recv().await.and_then(|raw_buf| {
190+
self.incoming.recv_async().await.ok().and_then(|raw_buf| {
192191
let (_v4_packet, tcp_packet) = parse_ipv4_packet(&raw_buf);
193192

194193
if (tcp_packet.get_flags() & tcp::TcpFlags::RST) != 0 {
@@ -231,7 +230,7 @@ impl Socket {
231230
info!("Sent SYN + ACK to client");
232231
}
233232
State::SynReceived => {
234-
let res = time::timeout(TIMEOUT, self.incoming.lock().await.recv()).await;
233+
let res = time::timeout(TIMEOUT, self.incoming.recv_async()).await;
235234
if let Ok(buf) = res {
236235
let buf = buf.unwrap();
237236
let (_v4_packet, tcp_packet) = parse_ipv4_packet(&buf);
@@ -275,7 +274,7 @@ impl Socket {
275274
info!("Sent SYN to server");
276275
}
277276
State::SynSent => {
278-
match time::timeout(TIMEOUT, self.incoming.lock().await.recv()).await {
277+
match time::timeout(TIMEOUT, self.incoming.recv_async()).await {
279278
Ok(buf) => {
280279
let buf = buf.unwrap();
281280
let (_v4_packet, tcp_packet) = parse_ipv4_packet(&buf);
@@ -426,7 +425,7 @@ impl Stack {
426425
shared: Arc<Shared>,
427426
mut tuples_purge: broadcast::Receiver<AddrTuple>,
428427
) {
429-
let mut tuples: HashMap<AddrTuple, Sender<Bytes>> = HashMap::new();
428+
let mut tuples: HashMap<AddrTuple, flume::Sender<Bytes>> = HashMap::new();
430429

431430
loop {
432431
let mut buf = BytesMut::with_capacity(MAX_PACKET_LEN);
@@ -450,7 +449,7 @@ impl Stack {
450449

451450
let tuple = AddrTuple::new(local_addr, remote_addr);
452451
if let Some(c) = tuples.get(&tuple) {
453-
if c.send(buf).await.is_err() {
452+
if c.send_async(buf).await.is_err() {
454453
trace!("Cache hit, but receiver already closed, dropping packet");
455454
}
456455

@@ -469,7 +468,7 @@ impl Stack {
469468
if let Some(c) = sender {
470469
trace!("Storing connection information into local tuples");
471470
tuples.insert(tuple, c.clone());
472-
c.send(buf).await.unwrap();
471+
c.send_async(buf).await.unwrap();
473472
continue;
474473
}
475474
}

0 commit comments

Comments
 (0)