Skip to content

Commit 3a26c36

Browse files
committed
hugetop: print human readable sizes by default
Consistent with the hugetop command of `procps-ng`, change the default size to a format suitable for human reading. 1. Node summary always human-readable; 2. Process columns respect -H flag Closes: #687
1 parent acab02f commit 3a26c36

1 file changed

Lines changed: 100 additions & 12 deletions

File tree

src/uu/hugetop/src/hugetop.rs

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7474
}
7575

7676
fn run(numa: bool, human: bool, limit: Option<usize>) -> UResult<()> {
77-
print_summary(numa, human);
77+
print_summary(numa);
7878
print_headings();
7979
print_procs(human, limit);
8080
Ok(())
@@ -122,14 +122,14 @@ pub fn uu_app() -> Command {
122122
)
123123
}
124124

125-
fn print_summary(numa: bool, human: bool) {
125+
fn print_summary(numa: bool) {
126126
let now: DateTime<Local> = Local::now();
127127
println!("hugetop - {}", now.format("%a %b %e %T %Y"));
128128

129129
let pools = match read_node_hugepage_pools() {
130130
Ok(nodes) if numa => {
131131
for (node, pools) in &nodes {
132-
print_node(node, pools, human);
132+
print_node(node, pools);
133133
}
134134
return;
135135
}
@@ -143,9 +143,9 @@ fn print_summary(numa: bool, human: bool) {
143143
println!("(no hugepage pools found)");
144144
return;
145145
}
146-
print_node("node(s)", &pools, human);
146+
print_node("node(s)", &pools);
147147
} else {
148-
print_node("node(s)", &pools, human);
148+
print_node("node(s)", &pools);
149149
}
150150
}
151151

@@ -176,7 +176,7 @@ fn print_procs(human: bool, limit: Option<usize>) {
176176
}
177177
}
178178

179-
fn print_node(node: &str, pools: &[HugePagePool], human: bool) {
179+
fn format_node_line(node: &str, pools: &[HugePagePool]) -> String {
180180
let mut line = String::new();
181181
line.push_str(node);
182182
line.push(':');
@@ -186,19 +186,19 @@ fn print_node(node: &str, pools: &[HugePagePool], human: bool) {
186186
line.push(',');
187187
}
188188

189-
let size = if human {
190-
humanized(pool.size_kb, false)
191-
} else {
192-
format!("{}kB", pool.size_kb)
193-
};
189+
let size = humanized(pool.size_kb, false);
194190

195191
line.push_str(&format!(
196192
" {} - {}/{}",
197193
size, pool.free_pages, pool.total_pages
198194
));
199195
}
200196

201-
println!("{}", line);
197+
line
198+
}
199+
200+
fn print_node(node: &str, pools: &[HugePagePool]) {
201+
println!("{}", format_node_line(node, pools));
202202
}
203203

204204
fn format_kb(kb: u64, human: bool) -> String {
@@ -463,4 +463,92 @@ mod tests {
463463
assert_eq!(pools[0].total_pages, 10);
464464
assert_eq!(pools[0].free_pages, 3);
465465
}
466+
467+
#[test]
468+
#[cfg(target_os = "linux")]
469+
fn format_kb_defaults_to_human_readable() {
470+
assert_eq!(format_kb(64, true), "64Ki");
471+
assert_eq!(format_kb(1536, true), "1.5Mi");
472+
assert_eq!(format_kb(1048576, true), "1.0Gi");
473+
}
474+
475+
#[test]
476+
#[cfg(target_os = "linux")]
477+
fn format_kb_non_human_readable() {
478+
assert_eq!(format_kb(64, false), "64");
479+
assert_eq!(format_kb(1536, false), "1536");
480+
assert_eq!(format_kb(1048576, false), "1048576");
481+
}
482+
483+
#[test]
484+
#[cfg(target_os = "linux")]
485+
fn format_node_line_uses_human_readable_sizes() {
486+
let pools = vec![HugePagePool {
487+
size_kb: 2048,
488+
total_pages: 10,
489+
free_pages: 3,
490+
reserved_pages: 2,
491+
surplus_pages: 1,
492+
}];
493+
494+
assert_eq!(
495+
format_node_line("node(s)", &pools),
496+
"node(s): 2.0Mi - 3/10"
497+
);
498+
}
499+
500+
#[test]
501+
#[cfg(target_os = "linux")]
502+
fn format_node_line_multiple_pools() {
503+
let pools = vec![
504+
HugePagePool {
505+
size_kb: 2048,
506+
total_pages: 10,
507+
free_pages: 3,
508+
reserved_pages: 2,
509+
surplus_pages: 1,
510+
},
511+
HugePagePool {
512+
size_kb: 1048576,
513+
total_pages: 2,
514+
free_pages: 1,
515+
reserved_pages: 0,
516+
surplus_pages: 0,
517+
},
518+
];
519+
520+
assert_eq!(
521+
format_node_line("node(s)", &pools),
522+
"node(s): 2.0Mi - 3/10, 1.0Gi - 1/2"
523+
);
524+
}
525+
526+
#[test]
527+
#[cfg(target_os = "linux")]
528+
fn humanized_si_units() {
529+
// si=true uses powers of 1000, suffix without "i"
530+
assert_eq!(humanized(0, true), "0B");
531+
assert_eq!(humanized(1, true), "1.0K"); // 1024 bytes → 1.0K
532+
assert_eq!(humanized(10, true), "10K"); // integer when value >= 10
533+
assert_eq!(humanized(1, false), "1.0Ki"); // binary: 1024 bytes → 1.0Ki
534+
assert_eq!(humanized(1024, true), "1.0M"); // 1024*1024 bytes → 1.0M
535+
}
536+
537+
#[test]
538+
#[cfg(target_os = "linux")]
539+
fn humanized_small_values() {
540+
// level==0: bytes < 100, return raw bytes with "B" suffix
541+
assert_eq!(humanized(0, false), "0B");
542+
assert_eq!(humanized(0, true), "0B");
543+
}
544+
545+
#[test]
546+
#[cfg(target_os = "linux")]
547+
fn humanized_integer_rounding() {
548+
// When value >= 10.0, use integer format (no decimal)
549+
// 10240 kiB → 10 MiB (10.0 >= 10 → integer)
550+
assert_eq!(humanized(10240, false), "10Mi");
551+
// 10485760 kiB → 10 GiB
552+
assert_eq!(humanized(10485760, false), "10Gi");
553+
}
466554
}

0 commit comments

Comments
 (0)