1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

ls: Optimize display_item_long

Preallocate output_display to a larger size, and use `extend`
instead of format.

Saves about ~5% performance vs baseline implementation.
This commit is contained in:
Nicolas Boichat 2025-04-19 18:40:13 +02:00
parent b009cae5a8
commit 8b9960f093

View file

@ -2760,11 +2760,11 @@ fn display_item_long(
style_manager: &mut Option<StyleManager>, style_manager: &mut Option<StyleManager>,
quoted: bool, quoted: bool,
) -> UResult<()> { ) -> UResult<()> {
let mut output_display: Vec<u8> = vec![]; let mut output_display: Vec<u8> = Vec::with_capacity(128);
// apply normal color to non filename outputs // apply normal color to non filename outputs
if let Some(style_manager) = style_manager { if let Some(style_manager) = style_manager {
write!(output_display, "{}", style_manager.apply_normal()).unwrap(); output_display.extend(style_manager.apply_normal().as_bytes());
} }
if config.dired { if config.dired {
output_display.extend(b" "); output_display.extend(b" ");
@ -2775,69 +2775,47 @@ fn display_item_long(
let is_acl_set = false; let is_acl_set = false;
#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] #[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))]
let is_acl_set = has_acl(item.display_name.as_os_str()); let is_acl_set = has_acl(item.display_name.as_os_str());
write!( output_display.extend(display_permissions(md, true).as_bytes());
output_display,
"{}{} {}",
display_permissions(md, true),
if item.security_context.len() > 1 { if item.security_context.len() > 1 {
// GNU `ls` uses a "." character to indicate a file with a security context, // GNU `ls` uses a "." character to indicate a file with a security context,
// but not other alternate access method. // but not other alternate access method.
"." output_display.extend(b".");
} else if is_acl_set { } else if is_acl_set {
"+" output_display.extend(b"+");
} else { }
"" output_display.extend(b" ");
}, output_display.extend(pad_left(&display_symlink_count(md), padding.link_count).as_bytes());
pad_left(&display_symlink_count(md), padding.link_count)
)
.unwrap();
if config.long.owner { if config.long.owner {
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_right(&display_uname(md, config), padding.uname).as_bytes());
" {}",
pad_right(&display_uname(md, config), padding.uname)
)
.unwrap();
} }
if config.long.group { if config.long.group {
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_right(&display_group(md, config), padding.group).as_bytes());
" {}",
pad_right(&display_group(md, config), padding.group)
)
.unwrap();
} }
if config.context { if config.context {
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_right(&item.security_context, padding.context).as_bytes());
" {}",
pad_right(&item.security_context, padding.context)
)
.unwrap();
} }
// Author is only different from owner on GNU/Hurd, so we reuse // Author is only different from owner on GNU/Hurd, so we reuse
// the owner, since GNU/Hurd is not currently supported by Rust. // the owner, since GNU/Hurd is not currently supported by Rust.
if config.long.author { if config.long.author {
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_right(&display_uname(md, config), padding.uname).as_bytes());
" {}",
pad_right(&display_uname(md, config), padding.uname)
)
.unwrap();
} }
match display_len_or_rdev(md, config) { match display_len_or_rdev(md, config) {
SizeOrDeviceId::Size(size) => { SizeOrDeviceId::Size(size) => {
write!(output_display, " {}", pad_left(&size, padding.size)).unwrap(); output_display.extend(b" ");
output_display.extend(pad_left(&size, padding.size).as_bytes());
} }
SizeOrDeviceId::Device(major, minor) => { SizeOrDeviceId::Device(major, minor) => {
write!( output_display.extend(b" ");
output_display, output_display.extend(
" {}, {}",
pad_left( pad_left(
&major, &major,
#[cfg(not(unix))] #[cfg(not(unix))]
@ -2846,22 +2824,28 @@ fn display_item_long(
padding.major.max( padding.major.max(
padding padding
.size .size
.saturating_sub(padding.minor.saturating_add(2usize)) .saturating_sub(padding.minor.saturating_add(2usize)),
),
), ),
)
.as_bytes(),
);
output_display.extend(b", ");
output_display.extend(
pad_left( pad_left(
&minor, &minor,
#[cfg(not(unix))] #[cfg(not(unix))]
0usize, 0usize,
#[cfg(unix)] #[cfg(unix)]
padding.minor, padding.minor,
),
) )
.unwrap(); .as_bytes(),
);
} }
}; };
write!(output_display, " {} ", display_date(md, config)).unwrap(); output_display.extend(b" ");
output_display.extend(display_date(md, config).as_bytes());
output_display.extend(b" ");
let item_name = display_item_name( let item_name = display_item_name(
item, item,
@ -2890,7 +2874,7 @@ fn display_item_long(
dired::update_positions(dired, start, end); dired::update_positions(dired, start, end);
} }
write_os_str(&mut output_display, &displayed_item)?; write_os_str(&mut output_display, &displayed_item)?;
write!(output_display, "{}", config.line_ending)?; output_display.extend(config.line_ending.to_string().as_bytes());
} else { } else {
#[cfg(unix)] #[cfg(unix)]
let leading_char = { let leading_char = {
@ -2925,42 +2909,36 @@ fn display_item_long(
} }
}; };
write!( output_display.extend(leading_char.as_bytes());
output_display, output_display.extend(b"?????????");
"{}{} {}",
format_args!("{leading_char}?????????"),
if item.security_context.len() > 1 { if item.security_context.len() > 1 {
// GNU `ls` uses a "." character to indicate a file with a security context, // GNU `ls` uses a "." character to indicate a file with a security context,
// but not other alternate access method. // but not other alternate access method.
"." output_display.extend(b".");
} else { }
"" output_display.extend(b" ");
}, output_display.extend(pad_left("?", padding.link_count).as_bytes());
pad_left("?", padding.link_count)
)
.unwrap();
if config.long.owner { if config.long.owner {
write!(output_display, " {}", pad_right("?", padding.uname)).unwrap(); output_display.extend(b" ");
output_display.extend(pad_right("?", padding.uname).as_bytes());
} }
if config.long.group { if config.long.group {
write!(output_display, " {}", pad_right("?", padding.group)).unwrap(); output_display.extend(b" ");
output_display.extend(pad_right("?", padding.group).as_bytes());
} }
if config.context { if config.context {
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_right(&item.security_context, padding.context).as_bytes());
" {}",
pad_right(&item.security_context, padding.context)
)
.unwrap();
} }
// Author is only different from owner on GNU/Hurd, so we reuse // Author is only different from owner on GNU/Hurd, so we reuse
// the owner, since GNU/Hurd is not currently supported by Rust. // the owner, since GNU/Hurd is not currently supported by Rust.
if config.long.author { if config.long.author {
write!(output_display, " {}", pad_right("?", padding.uname)).unwrap(); output_display.extend(b" ");
output_display.extend(pad_right("?", padding.uname).as_bytes());
} }
let displayed_item = display_item_name( let displayed_item = display_item_name(
@ -2974,13 +2952,11 @@ fn display_item_long(
); );
let date_len = 12; let date_len = 12;
write!( output_display.extend(b" ");
output_display, output_display.extend(pad_left("?", padding.size).as_bytes());
" {} {} ", output_display.extend(b" ");
pad_left("?", padding.size), output_display.extend(pad_left("?", date_len).as_bytes());
pad_left("?", date_len), output_display.extend(b" ");
)
.unwrap();
if config.dired { if config.dired {
dired::calculate_and_update_positions( dired::calculate_and_update_positions(
@ -2990,7 +2966,7 @@ fn display_item_long(
); );
} }
write_os_str(&mut output_display, &displayed_item)?; write_os_str(&mut output_display, &displayed_item)?;
write!(output_display, "{}", config.line_ending)?; output_display.extend(config.line_ending.to_string().as_bytes());
} }
out.write_all(&output_display)?; out.write_all(&output_display)?;