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) { pub fn wait(&mut self) {
self.stop();
if let Some(peer_thread) = self.peer_thread.take() { if let Some(peer_thread) = self.peer_thread.take() {
// wait only if other thread is calling us, eg shutdown // wait only if other thread is calling us, eg shutdown
if thread::current().id() != peer_thread.thread().id() { if thread::current().id() != peer_thread.thread().id() {
debug!("waiting for thread {:?} exit", peer_thread.thread().id()); debug!("waiting for thread {:?} exit", peer_thread.thread().id());
if let Err(e) = peer_thread.join() { 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 { } else {
debug!( debug!(
"attempt to stop thread {:?} from itself", "attempt to wait for thread {:?} from itself",
peer_thread.thread().id() peer_thread.thread().id()
); );
} }

View file

@ -397,18 +397,18 @@ impl Peer {
/// Stops the peer /// Stops the peer
pub fn stop(&self) { pub fn stop(&self) {
debug!("Stopping peer without waiting {:?}", self.info.addr); debug!("Stopping peer {:?}", self.info.addr);
match self.stop_handle.try_lock() { match self.stop_handle.try_lock() {
Some(handle) => handle.stop(), Some(handle) => handle.stop(),
None => error!("can't get stop lock for peer"), None => error!("can't get stop lock for peer"),
} }
} }
/// Stops the peer and wait until peer's thread exit /// Waits until the peer's thread exit
pub fn stop_and_wait(&self) { pub fn wait(&self) {
debug!("Stopping peer {:?}", self.info.addr); debug!("Waiting for peer {:?} to stop", self.info.addr);
match self.stop_handle.try_lock() { 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"), None => error!("can't get stop lock for peer"),
} }
} }

View file

@ -510,8 +510,11 @@ impl Peers {
pub fn stop(&self) { pub fn stop(&self) {
let mut peers = self.peers.write(); let mut peers = self.peers.write();
for peer in peers.values() {
peer.stop();
}
for (_, peer) in peers.drain() { for (_, peer) in peers.drain() {
peer.stop_and_wait(); peer.wait();
} }
} }