-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(daemon): limit number of git children (#9572)
### Description This PR limits the amount of `git` child sub processes that the daemon can start at one time so we don't flood the system with requests when many things change e.g. a during a rebase. ### Testing Instructions Added quick unit test to make sure we're using semaphore correctly. Did a manual test on a big repo and confirmed that on big changes and made sure that the number of `git` processes remain in the single digits now.
- Loading branch information
1 parent
4d02c7f
commit e7151e0
Showing
7 changed files
with
101 additions
and
6 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use std::{ops::Deref, sync::Arc}; | ||
|
||
use tokio::sync::{Semaphore, SemaphorePermit}; | ||
use turborepo_scm::SCM; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct SCMResource { | ||
scm: SCM, | ||
semaphore: Arc<Semaphore>, | ||
} | ||
|
||
pub struct SCMPermit<'a> { | ||
scm: &'a SCM, | ||
_permit: SemaphorePermit<'a>, | ||
} | ||
|
||
impl SCMResource { | ||
pub fn new(scm: SCM) -> Self { | ||
// We want to only take at most NUM_CPUS - 3 for git processes. | ||
// Accounting for the `turbo` process itself and the daemon this leaves one core | ||
// available for the rest of the system. | ||
let num_permits = num_cpus::get().saturating_sub(3).max(1); | ||
Self::new_with_permits(scm, num_permits) | ||
} | ||
|
||
fn new_with_permits(scm: SCM, num_permits: usize) -> Self { | ||
let semaphore = Arc::new(Semaphore::new(num_permits)); | ||
Self { scm, semaphore } | ||
} | ||
|
||
pub async fn acquire_scm(&self) -> SCMPermit { | ||
let _permit = self | ||
.semaphore | ||
.acquire() | ||
.await | ||
.expect("semaphore should not be closed"); | ||
SCMPermit { | ||
scm: &self.scm, | ||
_permit, | ||
} | ||
} | ||
} | ||
|
||
impl<'a> Deref for SCMPermit<'a> { | ||
type Target = SCM; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
self.scm | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use tokio::sync::oneshot; | ||
|
||
use super::*; | ||
|
||
#[tokio::test] | ||
async fn test_limits_access() { | ||
let scm = SCMResource::new_with_permits(SCM::Manual, 1); | ||
let scm_copy = scm.clone(); | ||
let permit_1 = scm.acquire_scm().await; | ||
let (other_tx, mut other_rx) = oneshot::channel(); | ||
tokio::task::spawn(async move { | ||
let _permit_2 = scm_copy.acquire_scm().await; | ||
other_tx.send(()).ok(); | ||
}); | ||
assert!( | ||
other_rx.try_recv().is_err(), | ||
"other should not have gotten a scm permit" | ||
); | ||
drop(permit_1); | ||
assert!( | ||
other_rx.await.is_ok(), | ||
"other should have gotten permit and exited" | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters