Skip to content

Commit ba20a8f

Browse files
perf(time): fuse compact numeric timestamps
1 parent adf227b commit ba20a8f

3 files changed

Lines changed: 115 additions & 1 deletion

File tree

crates/frankenlibc-abi/src/time_abi.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,47 @@ pub unsafe extern "C" fn strftime(
13881388
return n;
13891389
}
13901390
}
1391+
// `%Y%m%d%H%M%S\0` is the compact member of the same normalized
1392+
// numeric timestamp family. Its six directives otherwise enter the
1393+
// two-pass numeric interpreter, the largest candidate-only self-time
1394+
// in the whole-job profile. Match the full C string before projecting
1395+
// only the six fields this transducer consumes.
1396+
// SAFETY: strict mode trusts the caller's NUL-terminated C string; the
1397+
// short-circuit chain never reads past an earlier NUL.
1398+
if unsafe {
1399+
*format.cast::<u8>() == b'%'
1400+
&& *format.cast::<u8>().add(1) == b'Y'
1401+
&& *format.cast::<u8>().add(2) == b'%'
1402+
&& *format.cast::<u8>().add(3) == b'm'
1403+
&& *format.cast::<u8>().add(4) == b'%'
1404+
&& *format.cast::<u8>().add(5) == b'd'
1405+
&& *format.cast::<u8>().add(6) == b'%'
1406+
&& *format.cast::<u8>().add(7) == b'H'
1407+
&& *format.cast::<u8>().add(8) == b'%'
1408+
&& *format.cast::<u8>().add(9) == b'M'
1409+
&& *format.cast::<u8>().add(10) == b'%'
1410+
&& *format.cast::<u8>().add(11) == b'S'
1411+
&& *format.cast::<u8>().add(12) == 0
1412+
} {
1413+
// SAFETY: strict mode trusts the caller's valid `tm` object.
1414+
let (year, month, day, hour, minute, second) = unsafe {
1415+
(
1416+
(*tm).tm_year,
1417+
(*tm).tm_mon,
1418+
(*tm).tm_mday,
1419+
(*tm).tm_hour,
1420+
(*tm).tm_min,
1421+
(*tm).tm_sec,
1422+
)
1423+
};
1424+
// SAFETY: caller guarantees `s` writable for `maxsize` bytes.
1425+
let buf = unsafe { std::slice::from_raw_parts_mut(s as *mut u8, maxsize) };
1426+
if let Some(n) = time_core::format_strftime_compact_datetime(
1427+
year, month, day, hour, minute, second, buf,
1428+
) {
1429+
return n;
1430+
}
1431+
}
13911432
// Exact `%c\0` in FrankenLibC's C locale is the closed representation
13921433
// `%a %b %e %H:%M:%S %Y`. Compile that nested locale format into one
13931434
// fixed emitter before the generic C-string scan, full `tm` projection,

crates/frankenlibc-bench/examples/strftime_litrun_ab.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ fn verify(host: StrftimeFn, case: &Case, tm: &libc::tm) {
316316
}
317317
}
318318

319-
if case.label == "numeric_19" {
319+
if matches!(case.label, "numeric_19" | "compact_14") {
320320
for year in [1000, 9999] {
321321
for month in 0..=11 {
322322
for day in [1, 9, 10, 31] {

crates/frankenlibc-core/src/time/mod.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,9 @@ pub fn format_strftime(fmt: &[u8], bd: &BrokenDownTime, buf: &mut [u8]) -> usize
537537
if let Some(n) = format_strftime_numeric_19(fmt, bd, buf) {
538538
return n;
539539
}
540+
if let Some(n) = format_strftime_compact_14(fmt, bd, buf) {
541+
return n;
542+
}
540543
if let Some(n) = format_strftime_rfc3164(
541544
fmt, bd.tm_mon, bd.tm_mday, bd.tm_hour, bd.tm_min, bd.tm_sec, buf,
542545
) {
@@ -1682,6 +1685,62 @@ pub fn format_strftime_numeric_datetime(
16821685
Some(OUT_LEN)
16831686
}
16841687

1688+
#[inline]
1689+
fn format_strftime_compact_14(fmt: &[u8], bd: &BrokenDownTime, buf: &mut [u8]) -> Option<usize> {
1690+
if fmt != b"%Y%m%d%H%M%S" {
1691+
return None;
1692+
}
1693+
1694+
format_strftime_compact_datetime(
1695+
bd.tm_year, bd.tm_mon, bd.tm_mday, bd.tm_hour, bd.tm_min, bd.tm_sec, buf,
1696+
)
1697+
}
1698+
1699+
/// Emits the normalized, locale-independent `%Y%m%d%H%M%S` language.
1700+
///
1701+
/// This is the compact representation of the same closed field domain as
1702+
/// [`format_strftime_numeric_datetime`]. Callers retain the general formatter
1703+
/// as the fallback for non-normalized fields.
1704+
#[inline]
1705+
pub fn format_strftime_compact_datetime(
1706+
tm_year: i32,
1707+
month: i32,
1708+
day: i32,
1709+
hour: i32,
1710+
minute: i32,
1711+
second: i32,
1712+
buf: &mut [u8],
1713+
) -> Option<usize> {
1714+
let year = tm_year as i64 + 1900;
1715+
if !(1000..=9999).contains(&year)
1716+
|| !(0..=11).contains(&month)
1717+
|| !(1..=31).contains(&day)
1718+
|| !(0..=23).contains(&hour)
1719+
|| !(0..=59).contains(&minute)
1720+
|| !(0..=60).contains(&second)
1721+
{
1722+
return None;
1723+
}
1724+
1725+
const OUT_LEN: usize = 14;
1726+
if buf.len() <= OUT_LEN {
1727+
return Some(0);
1728+
}
1729+
1730+
let year = year as u32;
1731+
buf[0] = b'0' + ((year / 1000) % 10) as u8;
1732+
buf[1] = b'0' + ((year / 100) % 10) as u8;
1733+
buf[2] = b'0' + ((year / 10) % 10) as u8;
1734+
buf[3] = b'0' + (year % 10) as u8;
1735+
write_two_digits(&mut buf[4..6], (month + 1) as u32);
1736+
write_two_digits(&mut buf[6..8], day as u32);
1737+
write_two_digits(&mut buf[8..10], hour as u32);
1738+
write_two_digits(&mut buf[10..12], minute as u32);
1739+
write_two_digits(&mut buf[12..14], second as u32);
1740+
buf[OUT_LEN] = 0;
1741+
Some(OUT_LEN)
1742+
}
1743+
16851744
/// Formats the locale-independent fixed-width numeric subset without entering
16861745
/// the general flag/modifier parser. The first pass proves that the format has
16871746
/// at least one numeric directive, every directive is supported, every
@@ -2561,6 +2620,20 @@ mod tests {
25612620
assert_eq!(buf[19], 0);
25622621
}
25632622

2623+
#[test]
2624+
fn strftime_compact_14_exact_fit() {
2625+
let mut bd = epoch_to_broken_down(1_704_067_200);
2626+
bd.tm_hour = 14;
2627+
bd.tm_min = 30;
2628+
bd.tm_sec = 45;
2629+
let mut buf = [0x55u8; 15];
2630+
let n = format_strftime(b"%Y%m%d%H%M%S", &bd, &mut buf);
2631+
2632+
assert_eq!(n, 14);
2633+
assert_eq!(&buf[..14], b"20240101143045");
2634+
assert_eq!(buf[14], 0);
2635+
}
2636+
25642637
#[test]
25652638
fn strftime_hms_fast_path_exact_fit() {
25662639
let mut bd = epoch_to_broken_down(1_704_067_200);

0 commit comments

Comments
 (0)