Skip to content

Commit 2024274

Browse files
committed
perf(dameng): poll the interrupt every 200ms instead of every 10 seconds
1 parent d7a374f commit 2024274

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

dameng/src/client.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,15 @@ pub struct Client {
272272
pub interrupt: Arc<Interrupt>,
273273
}
274274

275+
/// How long a blocking read waits before the loop re-reads the cancel flag and the
276+
/// deadline. The socket timeout never bounded a statement: `read_message` checks
277+
/// `Interrupt` on the `WouldBlock` arm and loops, so this is poll granularity, and a
278+
/// long value only delays how soon a stop or a timeout is noticed.
279+
const POLL_INTERVAL: std::time::Duration = std::time::Duration::from_millis(200);
280+
281+
/// The connect and TLS handshake run before the poll loop owns the socket.
282+
const HANDSHAKE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
283+
275284
impl Client {
276285
/// Create a new client for the given host and port.
277286
pub fn new(host: &str, port: u16) -> Self {
@@ -306,8 +315,11 @@ impl Client {
306315
fn connect_stream(&mut self, use_ssl: bool) -> Result<()> {
307316
let addr = format!("{}:{}", self.host, self.port);
308317
let stream = TcpStream::connect(&addr)?;
309-
stream.set_read_timeout(Some(std::time::Duration::from_secs(10)))?;
310-
stream.set_write_timeout(Some(std::time::Duration::from_secs(10)))?;
318+
// The TLS handshake below reads through `native-tls`, which does not retry a
319+
// WouldBlock, so it keeps the long timeout. The poll interval is applied to the
320+
// established stream instead.
321+
stream.set_read_timeout(Some(HANDSHAKE_TIMEOUT))?;
322+
stream.set_write_timeout(Some(HANDSHAKE_TIMEOUT))?;
311323

312324
if use_ssl {
313325
let connector = TlsConnector::new()
@@ -319,6 +331,9 @@ impl Client {
319331
} else {
320332
self.stream = Some(Stream::Tcp(stream));
321333
}
334+
if let Some(stream) = self.stream.as_mut() {
335+
stream.set_read_timeout(Some(POLL_INTERVAL))?;
336+
}
322337
Ok(())
323338
}
324339

@@ -1180,9 +1195,7 @@ impl Client {
11801195
match stream.read(&mut tmp) {
11811196
Ok(0) => return None,
11821197
Ok(n) => buf.extend_from_slice(&tmp[..n]),
1183-
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {
1184-
std::thread::sleep(std::time::Duration::from_millis(10));
1185-
}
1198+
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {}
11861199
Err(e) => return Some(Err(Error::Io(e))),
11871200
}
11881201
}
@@ -1210,9 +1223,7 @@ impl Client {
12101223
)))
12111224
}
12121225
Ok(n) => buf.extend_from_slice(&tmp[..n]),
1213-
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {
1214-
std::thread::sleep(std::time::Duration::from_millis(10));
1215-
}
1226+
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {}
12161227
Err(e) => return Some(Err(Error::Io(e))),
12171228
}
12181229
}
@@ -1369,7 +1380,6 @@ impl Client {
13691380
Ok(n) => break n,
13701381
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {
13711382
interrupt.check(deadline)?;
1372-
std::thread::sleep(std::time::Duration::from_millis(10));
13731383
continue;
13741384
}
13751385
Err(e) => return Err(Error::Io(e)),
@@ -1400,7 +1410,6 @@ impl Client {
14001410
Ok(n) => break n,
14011411
Err(e) if e.kind() == ErrorKind::WouldBlock || e.raw_os_error() == Some(35) => {
14021412
interrupt.check(deadline)?;
1403-
std::thread::sleep(std::time::Duration::from_millis(10));
14041413
continue;
14051414
}
14061415
Err(e) => return Err(Error::Io(e)),
@@ -1707,4 +1716,15 @@ mod tests {
17071716
assert!(checked_lob_len(-1).is_err());
17081717
assert!(checked_lob_len(MAX_LOB_BYTES as i64 + 1).is_err());
17091718
}
1719+
1720+
/// A long read timeout is how soon a stop or a deadline is noticed, because
1721+
/// `read_message` only consults `Interrupt` on the `WouldBlock` arm. At ten seconds a
1722+
/// caller's cancel landed nine and a half seconds late and a one second statement
1723+
/// deadline fired at ten. `try_read_message`'s own shorter deadlines were unreachable
1724+
/// for the same reason.
1725+
#[test]
1726+
fn the_poll_interval_stays_short_enough_to_notice_a_stop() {
1727+
assert!(POLL_INTERVAL <= std::time::Duration::from_millis(250));
1728+
assert!(POLL_INTERVAL < HANDSHAKE_TIMEOUT);
1729+
}
17101730
}

0 commit comments

Comments
 (0)