Skip to content

Commit 5c15d79

Browse files
authored
ls: Lazily obtain FileType, eagerly obtain Metadata when Metadata is available (#8753)
Improves the ls perf by +10% in some cases
1 parent 4cab890 commit 5c15d79

File tree

4 files changed

+244
-213
lines changed

4 files changed

+244
-213
lines changed

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/ls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ansi-width = { workspace = true }
2424
clap = { workspace = true, features = ["env"] }
2525
glob = { workspace = true }
2626
hostname = { workspace = true }
27+
fnv = { workspace = true }
2728
lscolors = { workspace = true }
2829
selinux = { workspace = true, optional = true }
2930
terminal_size = { workspace = true }

src/uu/ls/src/colors.rs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55
use super::PathData;
6-
use super::get_metadata_with_deref_opt;
7-
use lscolors::{Indicator, LsColors, Style};
6+
use lscolors::{Colorable, Indicator, LsColors, Style};
87
use std::ffi::OsString;
9-
use std::fs::{DirEntry, Metadata};
10-
use std::io::{BufWriter, Stdout};
8+
use std::fs::Metadata;
119

1210
/// We need this struct to be able to store the previous style.
1311
/// This because we need to check the previous value in case we don't need
@@ -135,25 +133,22 @@ impl<'a> StyleManager<'a> {
135133
self.apply_style(style, name, wrap)
136134
}
137135

138-
pub(crate) fn apply_style_based_on_dir_entry(
136+
pub(crate) fn apply_style_based_on_colorable<T: Colorable>(
139137
&mut self,
140-
dir_entry: &DirEntry,
138+
path: &T,
141139
name: OsString,
142140
wrap: bool,
143141
) -> OsString {
144-
let style = self.colors.style_for(dir_entry);
142+
let style = self.colors.style_for(path);
145143
self.apply_style(style, name, wrap)
146144
}
147145
}
148146

149147
/// Colors the provided name based on the style determined for the given path
150-
/// This function is quite long because it tries to leverage [`DirEntry`] to avoid
151-
/// unnecessary calls to stat and manages the symlink errors
152148
pub(crate) fn color_name(
153149
name: OsString,
154150
path: &PathData,
155151
style_manager: &mut StyleManager,
156-
out: &mut BufWriter<Stdout>,
157152
target_symlink: Option<&PathData>,
158153
wrap: bool,
159154
) -> OsString {
@@ -179,23 +174,21 @@ pub(crate) fn color_name(
179174

180175
if !path.must_dereference {
181176
// If we need to dereference (follow) a symlink, we will need to get the metadata
182-
if let Some(de) = &path.de {
183-
// There is a DirEntry, we don't need to get the metadata for the color
184-
return style_manager.apply_style_based_on_dir_entry(de, name, wrap);
185-
}
177+
// There is a DirEntry, we don't need to get the metadata for the color
178+
return style_manager.apply_style_based_on_colorable(path, name, wrap);
186179
}
187180

188181
if let Some(target) = target_symlink {
189182
// use the optional target_symlink
190-
// Use fn get_metadata_with_deref_opt instead of get_metadata() here because ls
183+
// Use fn symlink_metadata directly instead of get_metadata() here because ls
191184
// should not exit with an err, if we are unable to obtain the target_metadata
192-
let md_res = get_metadata_with_deref_opt(&target.p_buf, path.must_dereference);
193-
let md = md_res.or_else(|_| path.p_buf.symlink_metadata());
194-
style_manager.apply_style_based_on_metadata(path, md.ok().as_ref(), name, wrap)
185+
style_manager.apply_style_based_on_colorable(target, name, wrap)
195186
} else {
196-
let md_option = path.get_metadata(out);
197-
let symlink_metadata = path.p_buf.symlink_metadata().ok();
198-
let md = md_option.or(symlink_metadata.as_ref());
199-
style_manager.apply_style_based_on_metadata(path, md, name, wrap)
187+
let md_option: Option<Metadata> = path
188+
.metadata()
189+
.cloned()
190+
.or_else(|| path.p_buf.symlink_metadata().ok());
191+
192+
style_manager.apply_style_based_on_metadata(path, md_option.as_ref(), name, wrap)
200193
}
201194
}

0 commit comments

Comments
 (0)