Skip to content

Commit 4966a54

Browse files
committed
refactor(files): rename read_mode_threshold fn
1 parent 00b0f8f commit 4966a54

File tree

6 files changed

+57
-35
lines changed

6 files changed

+57
-35
lines changed

.cspell.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ words:
99
- rustls
1010
- rustup
1111
- serde
12+
- uring
1213
- zstd

actix-files/CHANGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Unreleased
44

5-
- Opt-In filesize threshold for faster synchronus reads that allow for 20x better performance.
5+
- Add `{Files, NamedFile}::read_mode_threshold()` methods to allow faster synchronous reads of small files.
66
- Minimum supported Rust version (MSRV) is now 1.75.
77

88
## 0.6.6

actix-files/src/chunked.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ use pin_project_lite::pin_project;
1414

1515
use super::named::File;
1616

17+
#[derive(Debug, Clone, Copy)]
18+
pub(crate) enum ReadMode {
19+
Sync,
20+
Async,
21+
}
22+
1723
pin_project! {
1824
/// Adapter to read a `std::file::File` in chunks.
1925
#[doc(hidden)]
@@ -24,7 +30,7 @@ pin_project! {
2430
state: ChunkedReadFileState<Fut>,
2531
counter: u64,
2632
callback: F,
27-
read_sync: bool,
33+
read_mode: ReadMode,
2834
}
2935
}
3036

@@ -58,7 +64,7 @@ pub(crate) fn new_chunked_read(
5864
size: u64,
5965
offset: u64,
6066
file: File,
61-
size_threshold: u64,
67+
read_mode_threshold: u64,
6268
) -> impl Stream<Item = Result<Bytes, Error>> {
6369
ChunkedReadFile {
6470
size,
@@ -71,7 +77,11 @@ pub(crate) fn new_chunked_read(
7177
},
7278
counter: 0,
7379
callback: chunked_read_file_callback,
74-
read_sync: size < size_threshold,
80+
read_mode: if size < read_mode_threshold {
81+
ReadMode::Sync
82+
} else {
83+
ReadMode::Async
84+
},
7585
}
7686
}
7787

@@ -102,13 +112,14 @@ async fn chunked_read_file_callback(
102112
file: File,
103113
offset: u64,
104114
max_bytes: usize,
105-
read_sync: bool,
115+
read_mode: ReadMode,
106116
) -> Result<(File, Bytes), Error> {
107-
let res = if read_sync {
108-
chunked_read_file_callback_sync(file, offset, max_bytes)?
109-
} else {
110-
actix_web::web::block(move || chunked_read_file_callback_sync(file, offset, max_bytes))
111-
.await??
117+
let res = match read_mode {
118+
ReadMode::Sync => chunked_read_file_callback_sync(file, offset, max_bytes)?,
119+
ReadMode::Async => {
120+
actix_web::web::block(move || chunked_read_file_callback_sync(file, offset, max_bytes))
121+
.await??
122+
}
112123
};
113124

114125
Ok(res)
@@ -187,7 +198,7 @@ where
187198
#[cfg(not(feature = "experimental-io-uring"))]
188199
impl<F, Fut> Stream for ChunkedReadFile<F, Fut>
189200
where
190-
F: Fn(File, u64, usize, bool) -> Fut,
201+
F: Fn(File, u64, usize, ReadMode) -> Fut,
191202
Fut: Future<Output = Result<(File, Bytes), Error>>,
192203
{
193204
type Item = Result<Bytes, Error>;
@@ -209,7 +220,7 @@ where
209220
.take()
210221
.expect("ChunkedReadFile polled after completion");
211222

212-
let fut = (this.callback)(file, offset, max_bytes, *this.read_sync);
223+
let fut = (this.callback)(file, offset, max_bytes, *this.read_mode);
213224

214225
this.state
215226
.project_replace(ChunkedReadFileState::Future { fut });

actix-files/src/files.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub struct Files {
4949
use_guards: Option<Rc<dyn Guard>>,
5050
guards: Vec<Rc<dyn Guard>>,
5151
hidden_files: bool,
52-
size_threshold: u64,
52+
read_mode_threshold: u64,
5353
}
5454

5555
impl fmt::Debug for Files {
@@ -74,7 +74,7 @@ impl Clone for Files {
7474
use_guards: self.use_guards.clone(),
7575
guards: self.guards.clone(),
7676
hidden_files: self.hidden_files,
77-
size_threshold: self.size_threshold,
77+
read_mode_threshold: self.read_mode_threshold,
7878
}
7979
}
8080
}
@@ -121,7 +121,7 @@ impl Files {
121121
use_guards: None,
122122
guards: Vec::new(),
123123
hidden_files: false,
124-
size_threshold: 0,
124+
read_mode_threshold: 0,
125125
}
126126
}
127127

@@ -207,15 +207,20 @@ impl Files {
207207
self
208208
}
209209

210-
/// Sets the async file-size threshold.
210+
/// Sets the size threshold that determines file read mode (sync/async).
211211
///
212-
/// When a file is larger than the threshold, the reader
213-
/// will switch from faster blocking file-reads to slower async reads
214-
/// to avoid blocking the main-thread when processing large files.
212+
/// When a file is smaller than the threshold (bytes), the reader will switch from synchronous
213+
/// (blocking) file-reads to async reads to avoid blocking the main-thread when processing large
214+
/// files.
215215
///
216-
/// Default is 0, meaning all files are read asyncly.
217-
pub fn set_size_threshold(mut self, size: u64) -> Self {
218-
self.size_threshold = size;
216+
/// Tweaking this value according to your expected usage may lead to signifiant performance
217+
/// gains (or losses in other handlers, if `size` is too high).
218+
///
219+
/// When the `experimental-io-uring` crate feature is enabled, file reads are always async.
220+
///
221+
/// Default is 0, meaning all files are read asynchronously.
222+
pub fn read_mode_threshold(mut self, size: u64) -> Self {
223+
self.read_mode_threshold = size;
219224
self
220225
}
221226

@@ -382,7 +387,7 @@ impl ServiceFactory<ServiceRequest> for Files {
382387
file_flags: self.file_flags,
383388
guards: self.use_guards.clone(),
384389
hidden_files: self.hidden_files,
385-
size_threshold: self.size_threshold,
390+
size_threshold: self.read_mode_threshold,
386391
};
387392

388393
if let Some(ref default) = *self.default.borrow() {

actix-files/src/named.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub struct NamedFile {
8080
pub(crate) content_type: Mime,
8181
pub(crate) content_disposition: ContentDisposition,
8282
pub(crate) encoding: Option<ContentEncoding>,
83-
pub(crate) size_threshold: u64,
83+
pub(crate) read_mode_threshold: u64,
8484
}
8585

8686
#[cfg(not(feature = "experimental-io-uring"))]
@@ -201,7 +201,7 @@ impl NamedFile {
201201
encoding,
202202
status_code: StatusCode::OK,
203203
flags: Flags::default(),
204-
size_threshold: 0,
204+
read_mode_threshold: 0,
205205
})
206206
}
207207

@@ -355,15 +355,20 @@ impl NamedFile {
355355
self
356356
}
357357

358-
/// Sets the async file-size threshold.
358+
/// Sets the size threshold that determines file read mode (sync/async).
359359
///
360-
/// When a file is larger than the threshold, the reader
361-
/// will switch from faster blocking file-reads to slower async reads
362-
/// to avoid blocking the main-thread when processing large files.
360+
/// When a file is smaller than the threshold (bytes), the reader will switch from synchronous
361+
/// (blocking) file-reads to async reads to avoid blocking the main-thread when processing large
362+
/// files.
363363
///
364-
/// Default is 0, meaning all files are read asyncly.
365-
pub fn set_size_threshold(mut self, size: u64) -> Self {
366-
self.size_threshold = size;
364+
/// Tweaking this value according to your expected usage may lead to signifiant performance
365+
/// gains (or losses in other handlers, if `size` is too high).
366+
///
367+
/// When the `experimental-io-uring` crate feature is enabled, file reads are always async.
368+
///
369+
/// Default is 0, meaning all files are read asynchronously.
370+
pub fn read_mode_threshold(mut self, size: u64) -> Self {
371+
self.read_mode_threshold = size;
367372
self
368373
}
369374

@@ -455,7 +460,7 @@ impl NamedFile {
455460
}
456461

457462
let reader =
458-
chunked::new_chunked_read(self.md.len(), 0, self.file, self.size_threshold);
463+
chunked::new_chunked_read(self.md.len(), 0, self.file, self.read_mode_threshold);
459464

460465
return res.streaming(reader);
461466
}
@@ -592,7 +597,7 @@ impl NamedFile {
592597
.map_into_boxed_body();
593598
}
594599

595-
let reader = chunked::new_chunked_read(length, offset, self.file, self.size_threshold);
600+
let reader = chunked::new_chunked_read(length, offset, self.file, self.read_mode_threshold);
596601

597602
if offset != 0 || length != self.md.len() {
598603
res.status(StatusCode::PARTIAL_CONTENT);

actix-files/src/service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl FilesService {
7272

7373
let (req, _) = req.into_parts();
7474
let res = named_file
75-
.set_size_threshold(self.size_threshold)
75+
.read_mode_threshold(self.size_threshold)
7676
.into_response(&req);
7777
ServiceResponse::new(req, res)
7878
}

0 commit comments

Comments
 (0)