Skip to content

Commit 66b4450

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 66b4450

1 file changed

Lines changed: 97 additions & 12 deletions

File tree

src/uu/hugetop/src/hugetop.rs

Lines changed: 97 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,89 @@ 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!(format_node_line("node(s)", &pools), "node(s): 2.0Mi - 3/10");
495+
}
496+
497+
#[test]
498+
#[cfg(target_os = "linux")]
499+
fn format_node_line_multiple_pools() {
500+
let pools = vec![
501+
HugePagePool {
502+
size_kb: 2048,
503+
total_pages: 10,
504+
free_pages: 3,
505+
reserved_pages: 2,
506+
surplus_pages: 1,
507+
},
508+
HugePagePool {
509+
size_kb: 1048576,
510+
total_pages: 2,
511+
free_pages: 1,
512+
reserved_pages: 0,
513+
surplus_pages: 0,
514+
},
515+
];
516+
517+
assert_eq!(
518+
format_node_line("node(s)", &pools),
519+
"node(s): 2.0Mi - 3/10, 1.0Gi - 1/2"
520+
);
521+
}
522+
523+
#[test]
524+
#[cfg(target_os = "linux")]
525+
fn humanized_si_units() {
526+
// si=true uses powers of 1000, suffix without "i"
527+
assert_eq!(humanized(0, true), "0B");
528+
assert_eq!(humanized(1, true), "1.0K"); // 1024 bytes → 1.0K
529+
assert_eq!(humanized(10, true), "10K"); // integer when value >= 10
530+
assert_eq!(humanized(1, false), "1.0Ki"); // binary: 1024 bytes → 1.0Ki
531+
assert_eq!(humanized(1024, true), "1.0M"); // 1024*1024 bytes → 1.0M
532+
}
533+
534+
#[test]
535+
#[cfg(target_os = "linux")]
536+
fn humanized_small_values() {
537+
// level==0: bytes < 100, return raw bytes with "B" suffix
538+
assert_eq!(humanized(0, false), "0B");
539+
assert_eq!(humanized(0, true), "0B");
540+
}
541+
542+
#[test]
543+
#[cfg(target_os = "linux")]
544+
fn humanized_integer_rounding() {
545+
// When value >= 10.0, use integer format (no decimal)
546+
// 10240 kiB → 10 MiB (10.0 >= 10 → integer)
547+
assert_eq!(humanized(10240, false), "10Mi");
548+
// 10485760 kiB → 10 GiB
549+
assert_eq!(humanized(10485760, false), "10Gi");
550+
}
466551
}

0 commit comments

Comments
 (0)