Skip to content

Commit 0790d8b

Browse files
committed
add sequential file access hint on windows and where available on unix
1 parent 60d5886 commit 0790d8b

3 files changed

Lines changed: 40 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/uu/tsort/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ thiserror = { workspace = true }
2525
uucore = { workspace = true }
2626
rustc-hash = { workspace = true }
2727

28-
[target.'cfg(unix)'.dependencies]
28+
[target.'cfg(windows)'.dependencies]
29+
windows-sys = { workspace = true, features = ["Win32_Storage_FileSystem"] }
30+
31+
[target.'cfg(any(unix, target_os = "wasi"))'.dependencies]
2932
rustix = { workspace = true, features = ["fs"] }
3033

3134
[[bin]]

src/uu/tsort/src/tsort.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@
88

99
mod error;
1010

11+
use crate::error::{Error, ReadError};
1112
use clap::{Arg, ArgAction, Command};
1213
use rustc_hash::FxHashMap;
1314
use std::collections::VecDeque;
1415
use std::collections::hash_map::Entry;
1516
use std::ffi::OsString;
1617
use std::fs::File;
18+
use std::fs::OpenOptions;
1719
use std::io::{self, BufRead, BufReader, BufWriter, Write};
1820
use string_interner::StringInterner;
1921
use string_interner::backend::BucketBackend;
2022
use uucore::display::Quotable;
2123
use uucore::error::{FromIo, UError, UResult, USimpleError};
2224
use uucore::{format_usage, show, translate};
2325

24-
use crate::error::{Error, ReadError};
25-
2626
// short types for switching interning behavior on the fly.
2727
type Sym = string_interner::symbol::SymbolUsize;
2828
type Interner = StringInterner<BucketBackend<Sym>, rustc_hash::FxBuildHasher>;
@@ -57,19 +57,49 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5757
if input == "-" {
5858
process_input(io::stdin().lock(), &mut g)?;
5959
} else {
60+
let mut options: OpenOptions;
6061
// some platforms cannot catch this as read error. Needs additional cost by stat
6162
#[cfg(windows)]
6263
{
64+
use std::os::windows::fs::OpenOptionsExt;
65+
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_SEQUENTIAL_SCAN;
6366
let input = std::path::Path::new(input);
6467
if input.is_dir() {
6568
return Err(
6669
Error::Read(ReadError::IsDir(input.to_string_lossy().to_string())).into(),
6770
);
6871
}
72+
// advise the OS we will access the data sequentially if possible (windows)
73+
options = File::options()
74+
.custom_flags(FILE_FLAG_SEQUENTIAL_SCAN)
75+
.clone();
76+
}
77+
78+
#[cfg(not(windows))]
79+
{
80+
options = File::options();
6981
}
70-
let file = File::open(input).map_err_context(|| input.maybe_quote().to_string())?;
71-
// advise the OS we will access the data sequentially if possible
72-
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
82+
let file = options
83+
.read(true)
84+
.open(input)
85+
.map_err_context(|| input.maybe_quote().to_string())?;
86+
87+
// advise the OS we will access the data sequentially if possible (unix)
88+
#[cfg(all(
89+
any(unix, target_os = "wasi"),
90+
not(any(
91+
target_vendor = "apple",
92+
target_os = "netbsd",
93+
target_os = "openbsd",
94+
target_os = "dragonfly",
95+
target_os = "espidf",
96+
target_os = "haiku",
97+
target_os = "horizon",
98+
target_os = "redox",
99+
target_os = "solaris",
100+
target_os = "vita",
101+
))
102+
))]
73103
let _ = rustix::fs::fadvise(&file, 0, None, rustix::fs::Advice::Sequential);
74104

75105
let reader = BufReader::new(file);

0 commit comments

Comments
 (0)