We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Performance and Data Layout step 17 of 20
Build a report with a reusable string buffer
Format a report into one reusable string buffer while meeting an allocation budget.
pub fn render_report(rows: Vec<(String, i64)>) -> String
Write one line per input row, preserving order, with this format:
"{name:<12}{value:>10}\n"
The name is left-aligned in a minimum field width of 12. The integer is
right-aligned in a minimum field width of 10, including its minus sign.
Values and names wider than their fields are not truncated. There is no
additional separator between the two fields. Every line ends in \n.
After all rows, write a line in the same format with the name TOTAL and
the sum of the values. Empty input still produces "TOTAL 0\n".
Intermediate sums fit in i64, and the completed report fits in memory.
Names are inserted as supplied, without escaping or trimming.
For rows [("abc", 0), ("fghi", 1), ("klmno", 2)], the output is:
abc 0
fghi 1
klmno 2
TOTAL 3
What the allocation gate measures
The harness prepares the input before resetting its allocation counter. It
counts calls to allocate, allocate zeroed memory or reallocate during
render_report, allowing at most two in total. Deallocations are not counted.
Output inspection happens after the measured call.
The supplied cases include 3,000 rows. Their generated names are short ASCII strings and their values are small, but the formatting contract also permits longer names and wider integers. Reserve enough space for the actual input instead of assuming every line has the minimum width.
Avoid rebuilding the existing report
The starter uses this assignment for each row:
out = format!("{}{:<12}{:>10}\n", out, name, value);
Each call builds a new string containing the entire previous report and the next row. For similarly sized rows, copying every growing prefix makes the total copying work quadratic in the row count. The allocation count and timing depend on the input and implementation; a fixed slowdown is not a useful guarantee.
Instead, reserve a buffer once and append each formatted row to it:
use std::fmt::Write as _;
let mut out = String::with_capacity(capacity);
writeln!(out, "{name:<12}{value:>10}").unwrap();
This fragment assumes capacity, name and value are already available.
writeln! writes into the existing string without first building a separate
formatted string. The destination can still reallocate if its capacity is
insufficient.
Estimate capacity in bytes
String capacity is measured in UTF-8 bytes. String formatting width counts
Unicode scalar values, which can differ from both byte length and visual
display width. The number of padding spaces for a name is therefore
12usize.saturating_sub(name.chars().count()).
A conservative bound for one row is:
name.len() + name_padding + 20 + 1
Twenty bytes cover any decimal i64, including the sign of i64::MIN.
The final byte is the newline. Reserving 33 additional bytes covers the
padded TOTAL name, its integer and its newline. Sum the row bounds in a
first pass, then format the report in a second pass. A safe upper bound can
reserve more bytes than are ultimately written.
Handle formatting results in context
std::fmt::Write and std::io::Write are different traits. Formatting macros
work with both, but this function uses the text-formatting trait for String.
Its methods return fmt::Result so other formatting destinations can report
failure. Formatting ordinary strings and integers into a String does not
produce a formatting error, so unwrap() is appropriate here. Allocation
failure is a separate concern, not a recoverable fmt::Error from this call.
Keep the output exact while removing temporary strings. Compile, check the expected text and allocation count, and address Clippy warnings.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.