Skip to content

Commit 5144688

Browse files
committed
storage: use global thread pool to support prefetch
Currently we use a prefetch manager per backend, this design has two drawbacks: - spawn too many worker threads for prefetch - the network ratelimit has been defunct So change the design to use a global prefetch manager with thread pool to supporrt all prefetch requests. Signed-off-by: Jiang Liu <[email protected]>
1 parent fb8db88 commit 5144688

File tree

4 files changed

+243
-225
lines changed

4 files changed

+243
-225
lines changed

storage/src/cache/cachedfile.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use tokio::runtime::Runtime;
2727

2828
use crate::backend::BlobReader;
2929
use crate::cache::state::ChunkMap;
30-
use crate::cache::worker::{AsyncPrefetchConfig, AsyncPrefetchMessage, AsyncWorkerMgr};
30+
use crate::cache::worker::{AsyncPrefetchConfig, AsyncPrefetchMessage, PrefetchMgr};
3131
use crate::cache::{BlobCache, BlobIoMergeState};
3232
use crate::device::{
3333
BlobChunkInfo, BlobInfo, BlobIoDesc, BlobIoRange, BlobIoSegment, BlobIoTag, BlobIoVec,
@@ -134,9 +134,9 @@ pub(crate) struct FileCacheEntry {
134134
pub(crate) meta: Option<FileCacheMeta>,
135135
pub(crate) metrics: Arc<BlobcacheMetrics>,
136136
pub(crate) prefetch_state: Arc<AtomicU32>,
137+
pub(crate) prefetch_mgr: Arc<PrefetchMgr>,
137138
pub(crate) reader: Arc<dyn BlobReader>,
138139
pub(crate) runtime: Arc<Runtime>,
139-
pub(crate) workers: Arc<AsyncWorkerMgr>,
140140

141141
pub(crate) blob_compressed_size: u64,
142142
pub(crate) blob_uncompressed_size: u64,
@@ -458,7 +458,8 @@ impl BlobCache for FileCacheEntry {
458458
warn!("storage: inaccurate prefetch status");
459459
}
460460
if val == 0 || val == 1 {
461-
self.workers.flush_pending_prefetch_requests(&self.blob_id);
461+
self.prefetch_mgr
462+
.flush_pending_prefetch_requests(&self.blob_id);
462463
return Ok(());
463464
}
464465
}
@@ -477,11 +478,12 @@ impl BlobCache for FileCacheEntry {
477478
// Handle blob prefetch request first, it may help performance.
478479
for req in prefetches {
479480
let msg = AsyncPrefetchMessage::new_blob_prefetch(
481+
self.prefetch_mgr.clone(),
480482
blob_cache.clone(),
481483
req.offset as u64,
482484
req.len as u64,
483485
);
484-
let _ = self.workers.send_prefetch_message(msg);
486+
let _ = self.prefetch_mgr.send_prefetch_message(msg);
485487
}
486488

487489
// Then handle fs prefetch
@@ -494,8 +496,12 @@ impl BlobCache for FileCacheEntry {
494496
max_comp_size,
495497
max_comp_size as u64 >> RAFS_BATCH_SIZE_TO_GAP_SHIFT,
496498
|req: BlobIoRange| {
497-
let msg = AsyncPrefetchMessage::new_fs_prefetch(blob_cache.clone(), req);
498-
let _ = self.workers.send_prefetch_message(msg);
499+
let msg = AsyncPrefetchMessage::new_fs_prefetch(
500+
self.prefetch_mgr.clone(),
501+
blob_cache.clone(),
502+
req,
503+
);
504+
let _ = self.prefetch_mgr.send_prefetch_message(msg);
499505
},
500506
);
501507

@@ -593,7 +599,7 @@ impl BlobCache for FileCacheEntry {
593599

594600
fn read(&self, iovec: &mut BlobIoVec, buffers: &[FileVolatileSlice]) -> Result<usize> {
595601
self.metrics.total.inc();
596-
self.workers.consume_prefetch_budget(iovec.size());
602+
self.prefetch_mgr.consume_prefetch_budget(iovec.size());
597603

598604
if iovec.is_empty() {
599605
Ok(0)

storage/src/cache/filecache/mod.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::cache::cachedfile::{FileCacheEntry, FileCacheMeta};
1919
use crate::cache::state::{
2020
BlobStateMap, ChunkMap, DigestedChunkMap, IndexedChunkMap, NoopChunkMap,
2121
};
22-
use crate::cache::worker::{AsyncPrefetchConfig, AsyncWorkerMgr};
22+
use crate::cache::worker::{AsyncPrefetchConfig, PrefetchMgr};
2323
use crate::cache::{BlobCache, BlobCacheMgr};
2424
use crate::device::{BlobFeatures, BlobInfo};
2525
use crate::RAFS_DEFAULT_CHUNK_SIZE;
@@ -32,8 +32,8 @@ pub struct FileCacheMgr {
3232
backend: Arc<dyn BlobBackend>,
3333
metrics: Arc<BlobcacheMetrics>,
3434
prefetch_config: Arc<AsyncPrefetchConfig>,
35+
prefetch_mgr: Arc<PrefetchMgr>,
3536
runtime: Arc<Runtime>,
36-
worker_mgr: Arc<AsyncWorkerMgr>,
3737
work_dir: String,
3838
validate: bool,
3939
disable_indexed_map: bool,
@@ -53,15 +53,15 @@ impl FileCacheMgr {
5353
let work_dir = blob_cfg.get_work_dir()?;
5454
let metrics = BlobcacheMetrics::new(id, work_dir);
5555
let prefetch_config: Arc<AsyncPrefetchConfig> = Arc::new((&config.prefetch).into());
56-
let worker_mgr = AsyncWorkerMgr::new(metrics.clone(), prefetch_config.clone())?;
56+
let worker_mgr = PrefetchMgr::new(metrics.clone(), prefetch_config.clone())?;
5757

5858
Ok(FileCacheMgr {
5959
blobs: Arc::new(RwLock::new(HashMap::new())),
6060
backend,
6161
metrics,
6262
prefetch_config,
6363
runtime,
64-
worker_mgr: Arc::new(worker_mgr),
64+
prefetch_mgr: Arc::new(worker_mgr),
6565
work_dir: work_dir.to_owned(),
6666
disable_indexed_map: blob_cfg.disable_indexed_map,
6767
validate: config.cache_validate,
@@ -87,7 +87,7 @@ impl FileCacheMgr {
8787
blob.clone(),
8888
self.prefetch_config.clone(),
8989
self.runtime.clone(),
90-
self.worker_mgr.clone(),
90+
self.prefetch_mgr.clone(),
9191
)?;
9292
let entry = Arc::new(entry);
9393
let mut guard = self.blobs.write().unwrap();
@@ -108,13 +108,12 @@ impl FileCacheMgr {
108108

109109
impl BlobCacheMgr for FileCacheMgr {
110110
fn init(&self) -> Result<()> {
111-
AsyncWorkerMgr::start(self.worker_mgr.clone())
111+
self.prefetch_mgr.setup()
112112
}
113113

114114
fn destroy(&self) {
115115
if !self.closed.load(Ordering::Acquire) {
116116
self.closed.store(true, Ordering::Release);
117-
self.worker_mgr.stop();
118117
self.backend().shutdown();
119118
self.metrics.release().unwrap_or_else(|e| error!("{:?}", e));
120119
}
@@ -170,7 +169,7 @@ impl FileCacheEntry {
170169
blob_info: Arc<BlobInfo>,
171170
prefetch_config: Arc<AsyncPrefetchConfig>,
172171
runtime: Arc<Runtime>,
173-
workers: Arc<AsyncWorkerMgr>,
172+
prefetch_mgr: Arc<PrefetchMgr>,
174173
) -> Result<Self> {
175174
let is_separate_meta = blob_info.has_feature(BlobFeatures::SEPARATE);
176175
let is_tarfs = blob_info.features().is_tarfs();
@@ -296,7 +295,7 @@ impl FileCacheEntry {
296295
prefetch_state: Arc::new(AtomicU32::new(0)),
297296
reader,
298297
runtime,
299-
workers,
298+
prefetch_mgr,
300299

301300
blob_compressed_size,
302301
blob_uncompressed_size,

storage/src/cache/fscache/mod.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use tokio::runtime::Runtime;
1616
use crate::backend::BlobBackend;
1717
use crate::cache::cachedfile::{FileCacheEntry, FileCacheMeta};
1818
use crate::cache::state::{BlobStateMap, IndexedChunkMap, RangeMap};
19-
use crate::cache::worker::{AsyncPrefetchConfig, AsyncWorkerMgr};
19+
use crate::cache::worker::{AsyncPrefetchConfig, PrefetchMgr};
2020
use crate::cache::{BlobCache, BlobCacheMgr};
2121
use crate::device::{BlobFeatures, BlobInfo, BlobObject};
2222
use crate::factory::BLOB_FACTORY;
@@ -32,8 +32,8 @@ pub struct FsCacheMgr {
3232
backend: Arc<dyn BlobBackend>,
3333
metrics: Arc<BlobcacheMetrics>,
3434
prefetch_config: Arc<AsyncPrefetchConfig>,
35+
prefetch_mgr: Arc<PrefetchMgr>,
3536
runtime: Arc<Runtime>,
36-
worker_mgr: Arc<AsyncWorkerMgr>,
3737
work_dir: String,
3838
need_validation: bool,
3939
blobs_check_count: Arc<AtomicU8>,
@@ -56,7 +56,7 @@ impl FsCacheMgr {
5656
let work_dir = blob_cfg.get_work_dir()?;
5757
let metrics = BlobcacheMetrics::new(id, work_dir);
5858
let prefetch_config: Arc<AsyncPrefetchConfig> = Arc::new((&config.prefetch).into());
59-
let worker_mgr = AsyncWorkerMgr::new(metrics.clone(), prefetch_config.clone())?;
59+
let worker_mgr = PrefetchMgr::new(metrics.clone(), prefetch_config.clone())?;
6060

6161
BLOB_FACTORY.start_mgr_checker();
6262

@@ -66,7 +66,7 @@ impl FsCacheMgr {
6666
metrics,
6767
prefetch_config,
6868
runtime,
69-
worker_mgr: Arc::new(worker_mgr),
69+
prefetch_mgr: Arc::new(worker_mgr),
7070
work_dir: work_dir.to_owned(),
7171
need_validation: config.cache_validate,
7272
blobs_check_count: Arc::new(AtomicU8::new(0)),
@@ -91,7 +91,7 @@ impl FsCacheMgr {
9191
blob.clone(),
9292
self.prefetch_config.clone(),
9393
self.runtime.clone(),
94-
self.worker_mgr.clone(),
94+
self.prefetch_mgr.clone(),
9595
)?;
9696
let entry = Arc::new(entry);
9797
let mut guard = self.blobs.write().unwrap();
@@ -112,13 +112,12 @@ impl FsCacheMgr {
112112

113113
impl BlobCacheMgr for FsCacheMgr {
114114
fn init(&self) -> Result<()> {
115-
AsyncWorkerMgr::start(self.worker_mgr.clone())
115+
self.prefetch_mgr.setup()
116116
}
117117

118118
fn destroy(&self) {
119119
if !self.closed.load(Ordering::Acquire) {
120120
self.closed.store(true, Ordering::Release);
121-
self.worker_mgr.stop();
122121
self.backend().shutdown();
123122
self.metrics.release().unwrap_or_else(|e| error!("{:?}", e));
124123
}
@@ -173,7 +172,6 @@ impl BlobCacheMgr for FsCacheMgr {
173172
// we should double check blobs stat, in case some blobs hadn't been created when we checked.
174173
if all_ready {
175174
if self.blobs_check_count.load(Ordering::Acquire) == FSCACHE_BLOBS_CHECK_NUM {
176-
self.worker_mgr.stop();
177175
self.metrics.data_all_ready.store(true, Ordering::Release);
178176
} else {
179177
self.blobs_check_count.fetch_add(1, Ordering::Acquire);
@@ -196,7 +194,7 @@ impl FileCacheEntry {
196194
blob_info: Arc<BlobInfo>,
197195
prefetch_config: Arc<AsyncPrefetchConfig>,
198196
runtime: Arc<Runtime>,
199-
workers: Arc<AsyncWorkerMgr>,
197+
prefetch_mgr: Arc<PrefetchMgr>,
200198
) -> Result<Self> {
201199
if blob_info.has_feature(BlobFeatures::_V5_NO_EXT_BLOB_TABLE) {
202200
return Err(einval!("fscache does not support Rafs v5 blobs"));
@@ -269,7 +267,7 @@ impl FileCacheEntry {
269267
prefetch_state: Arc::new(AtomicU32::new(0)),
270268
reader,
271269
runtime,
272-
workers,
270+
prefetch_mgr,
273271

274272
blob_compressed_size,
275273
blob_uncompressed_size: blob_info.uncompressed_size(),

0 commit comments

Comments
 (0)