Skip to content

Commit

Permalink
Speedup shutdown (#2862)
Browse files Browse the repository at this point in the history
I made an suboptimal (aka stupid) decision to stop and wait for peers
one by one which makes shutdown very slow - O(n). This PR decouples sending
stop signal from waiting a thread to exit. On top of it in Peers we
first send stop signal to all peers and only after that start waiting
for them to exit. It gives us a constant time of shutdown in most of the
cases.
  • Loading branch information
hashmap authored and garyyu committed May 30, 2019
1 parent a1f71de commit 2863ed6
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 10 deletions.
7 changes: 3 additions & 4 deletions p2p/src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,17 @@ impl StopHandle {
}
}

pub fn stop_and_wait(&mut self) {
self.stop();
pub fn wait(&mut self) {
if let Some(peer_thread) = self.peer_thread.take() {
// wait only if other thread is calling us, eg shutdown
if thread::current().id() != peer_thread.thread().id() {
debug!("waiting for thread {:?} exit", peer_thread.thread().id());
if let Err(e) = peer_thread.join() {
error!("failed to stop peer thread: {:?}", e);
error!("failed to wait for peer thread to stop: {:?}", e);
}
} else {
debug!(
"attempt to stop thread {:?} from itself",
"attempt to wait for thread {:?} from itself",
peer_thread.thread().id()
);
}
Expand Down
10 changes: 5 additions & 5 deletions p2p/src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,18 +397,18 @@ impl Peer {

/// Stops the peer
pub fn stop(&self) {
debug!("Stopping peer without waiting {:?}", self.info.addr);
debug!("Stopping peer {:?}", self.info.addr);
match self.stop_handle.try_lock() {
Some(handle) => handle.stop(),
None => error!("can't get stop lock for peer"),
}
}

/// Stops the peer and wait until peer's thread exit
pub fn stop_and_wait(&self) {
debug!("Stopping peer {:?}", self.info.addr);
/// Waits until the peer's thread exit
pub fn wait(&self) {
debug!("Waiting for peer {:?} to stop", self.info.addr);
match self.stop_handle.try_lock() {
Some(mut handle) => handle.stop_and_wait(),
Some(mut handle) => handle.wait(),
None => error!("can't get stop lock for peer"),
}
}
Expand Down
5 changes: 4 additions & 1 deletion p2p/src/peers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,11 @@ impl Peers {

pub fn stop(&self) {
let mut peers = self.peers.write();
for peer in peers.values() {
peer.stop();
}
for (_, peer) in peers.drain() {
peer.stop_and_wait();
peer.wait();
}
}

Expand Down

0 comments on commit 2863ed6

Please sign in to comment.