Speedup shutdown (#2862)

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.
This commit is contained in:
hashmap 2019-05-30 02:03:12 +02:00 committed by Gary Yu
parent a1f71deba0
commit 2863ed67fd
3 changed files with 12 additions and 10 deletions

View file

@ -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()
);
}

View file

@ -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"),
}
}

View file

@ -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();
}
}