Skip to content

Commit dfc3c50

Browse files
muirdmmeta-codesync[bot]
authored andcommitted
backingstore: add walk-prefetch-skip-lfs config flag
Summary: Add `backingstore.walk-prefetch-skip-lfs` config flag (default: true) that causes walk file prefetching to skip LFS files. This avoids wasting bandwidth on large LFS blob fetches during background walk prefetches, which are speculative and may never be needed. Reviewed By: zzl0 Differential Revision: D98202367 fbshipit-source-id: 3715847e71362c13d965513260da879ce36955ad
1 parent 30596f4 commit dfc3c50

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

eden/scm/lib/backingstore/src/backingstore.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ impl BackingStore {
254254
"walk-prefetch-min-interval",
255255
|| Duration::from_millis(10),
256256
)?,
257+
skip_lfs: config.get_or("backingstore", "walk-prefetch-skip-lfs", || true)?,
257258
};
258259

259260
prefetch_manager(

eden/scm/lib/backingstore/src/prefetch.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub(crate) struct Config {
5151
pub(crate) max_initial_lag: u64,
5252
pub(crate) min_ratio: f64,
5353
pub(crate) min_interval: Duration,
54+
pub(crate) skip_lfs: bool,
5455
}
5556

5657
impl Default for Config {
@@ -59,6 +60,7 @@ impl Default for Config {
5960
max_initial_lag: 1000,
6061
min_ratio: 0.1,
6162
min_interval: Duration::from_millis(10),
63+
skip_lfs: true,
6264
}
6365
}
6466
}
@@ -484,7 +486,8 @@ fn prefetch(
484486
let fctx = FetchContext::new_with_mode_and_cause(
485487
FetchMode::AllowRemote | FetchMode::IGNORE_RESULT,
486488
FetchCause::EdenWalkPrefetch,
487-
);
489+
)
490+
.with_skip_lfs(config.skip_lfs);
488491

489492
// An important implementation detail for us: the scmstore FileStore spawns a thread
490493
// when you fetch more than 1_000 keys (i.e. this method will operate asynchronously if
@@ -1247,12 +1250,51 @@ mod test {
12471250
assert!(handle.is_paused());
12481251
}
12491252

1253+
#[test]
1254+
fn test_config_skip_lfs_defaults_true() {
1255+
let config = Config::default();
1256+
assert!(config.skip_lfs);
1257+
}
1258+
1259+
#[test]
1260+
fn test_prefetch_passes_skip_lfs() -> anyhow::Result<()> {
1261+
let tree_store = Arc::new(TestStore::new());
1262+
let file_store = Arc::new(TestStore::new());
1263+
1264+
let path: RepoPathBuf = "file.txt".to_string().try_into()?;
1265+
let hgid = file_store.insert_data(Default::default(), &path, b"content".into())?;
1266+
1267+
let mut mf = TreeManifest::ephemeral(tree_store);
1268+
mf.insert(path, FileMetadata::new(hgid, types::FileType::Regular))?;
1269+
1270+
let detector = walkdetector::Detector::new();
1271+
let handle = prefetch(
1272+
Config::default(),
1273+
mf,
1274+
file_store.clone(),
1275+
detector,
1276+
PrefetchWork::FileContent("".to_string().try_into()?, 0, None),
1277+
None,
1278+
);
1279+
1280+
while !handle.is_done() {
1281+
std::thread::sleep(Duration::from_millis(1));
1282+
}
1283+
1284+
let contexts = file_store.fetch_contexts();
1285+
assert_eq!(contexts.len(), 1);
1286+
assert!(contexts[0].skip_lfs());
1287+
1288+
Ok(())
1289+
}
1290+
12501291
#[test]
12511292
fn test_should_pause_prefetch() -> anyhow::Result<()> {
12521293
let config = Config {
12531294
min_ratio: 0.1,
12541295
max_initial_lag: 20,
12551296
min_interval: Duration::from_millis(1),
1297+
..Default::default()
12561298
};
12571299

12581300
let mut detector = walkdetector::Detector::new();

eden/scm/lib/manifest-tree/src/testutil.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub struct TestStoreInner {
6767
entries: HashMap<HgId, Bytes>,
6868
// Calls to get_content_iter().
6969
fetched: Vec<Vec<Key>>,
70+
// FetchContexts passed to get_content_iter().
71+
fetch_contexts: Vec<FetchContext>,
7072
// Parents recorded via insert_data with InsertOpts.parents.
7173
parents: HashMap<(RepoPathBuf, HgId), Vec<HgId>>,
7274
format: SerializationFormat,
@@ -89,6 +91,11 @@ impl TestStore {
8991
self.inner.read().fetched.clone()
9092
}
9193

94+
#[allow(unused)]
95+
pub fn fetch_contexts(&self) -> Vec<FetchContext> {
96+
self.inner.read().fetch_contexts.clone()
97+
}
98+
9299
pub fn key_fetch_count(&self) -> u64 {
93100
self.inner.read().key_fetch_count.load(Ordering::Relaxed)
94101
}
@@ -109,14 +116,15 @@ impl TestStore {
109116
impl KeyStore for TestStore {
110117
fn get_content_iter(
111118
&self,
112-
_fctx: FetchContext,
119+
fctx: FetchContext,
113120
keys: Vec<Key>,
114121
) -> anyhow::Result<BoxIterator<anyhow::Result<(Key, Blob)>>> {
115122
let mut inner = self.inner.write();
116123
inner
117124
.key_fetch_count
118125
.fetch_add(keys.len() as u64, Ordering::Relaxed);
119126
inner.fetched.push(keys.clone());
127+
inner.fetch_contexts.push(fctx);
120128
let entries = inner.entries.clone();
121129
drop(inner);
122130
let iter = keys

0 commit comments

Comments
 (0)