#![allow(clippy::all, clippy::pedantic, clippy::restriction, warnings)]
#[cfg(feature = "perf-tests")]
mod perf_tests {
use deep_time::civil_parts::Parts;
use deep_time::{Dt, Lang, ParseCfg, Scale};
use std::time::Instant;
#[test]
fn combined_perf_tests() {
let mut gps_deep_ns = 0.0f64;
let mut gps_hifi_ns = 0.0f64;
let mut tow_deep_ns = 0.0f64;
let mut tow_hifi_ns = 0.0f64;
let mut tai_utc_deep_ns = 0.0f64;
let mut tai_utc_hifi_ns = 0.0f64;
let mut utc_tai_deep_ns = 0.0f64;
let mut utc_tai_hifi_ns = 0.0f64;
let mut tai_tdb_deep_ns = 0.0f64;
let mut tai_tdb_hifi_ns = 0.0f64;
let mut tdb_tai_deep_ns = 0.0f64;
let mut tdb_tai_hifi_ns = 0.0f64;
let mut auto_ns_per = 0.0f64;
let mut strptime_timeparts_ns = 0.0f64;
let mut strptime_jiff_ns = 0.0f64;
let mut zoned_deep_ns = 0.0f64;
let mut zoned_jiff_ns = 0.0f64;
let mut iso_deep_ns = 0.0f64;
let mut iso_jiff_ns = 0.0f64;
let mut strftime_deep_ns = 0.0f64;
let mut strftime_jiff_ns = 0.0f64;
{
use hifitime::{Epoch, TimeScale};
use std::hint::black_box;
const ITERATIONS: usize = 10_000_000;
let deep_tai = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let hifi_tai = Epoch::from_gregorian_tai(2000, 1, 1, 12, 0, 0, 0);
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_tai).to_gps();
}
gps_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_tai).to_time_scale(black_box(TimeScale::GPST));
}
gps_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_tai).to_gps_wk_and_tow();
}
tow_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_tai).to_gpst_seconds();
}
tow_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
use hifitime::{Epoch, TimeScale};
use std::hint::black_box;
const ITERATIONS: usize = 10_000_000;
let deep_tai = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let hifi_tai = Epoch::from_gregorian_tai(2000, 1, 1, 0, 0, 0, 0);
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_tai).to(black_box(Scale::UTC));
}
tai_utc_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_tai).to_time_scale(black_box(TimeScale::UTC));
}
tai_utc_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let deep_utc = deep_tai.to(Scale::UTC);
let hifi_utc = hifi_tai.to_time_scale(TimeScale::UTC);
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_utc).to(black_box(Scale::TAI));
}
utc_tai_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_utc).to_time_scale(black_box(TimeScale::TAI));
}
utc_tai_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
use hifitime::{Epoch, TimeScale};
use std::hint::black_box;
const ITERATIONS: usize = 1_000_000;
let deep_tai = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let hifi_tai = Epoch::from_gregorian_tai(2000, 1, 1, 12, 0, 0, 0);
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_tai).to(black_box(Scale::TDB));
}
tai_tdb_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_tai).to_time_scale(black_box(TimeScale::TDB));
}
tai_tdb_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let deep_tdb = deep_tai.to(Scale::TDB);
let hifi_tdb = hifi_tai.to_time_scale(TimeScale::TDB);
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(deep_tdb).to(black_box(Scale::TAI));
}
tdb_tai_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = Instant::now();
for _ in 0..ITERATIONS {
let _ = black_box(hifi_tdb).to_time_scale(black_box(TimeScale::TAI));
}
tdb_tai_hifi_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
let cases: Vec<&str> = vec![
"2024-03-14",
"14 Mar 2024",
"Mar 14, 2024",
"2024/03/14",
"14.03.2024",
"14/03/2024",
"240314",
"202403",
"2024073",
"24073",
"60400",
"2460000",
"1700000000",
"1700000000000",
"15/03/2024 14:30:45.123456",
"Mar 15, 2024 14:30",
"2024-03-14T15:30:45.123456Z",
"2024-03-14T15:30:45+01:00",
"15/03/2024 14:30:45.123456789",
"03/03/2024",
"2024-074T15:30:45.123Z",
"240315",
"-2024-03-14",
"2024-03-14 15:30",
"15 Mar 2024 14:30:45",
];
const ITERATIONS: usize = 100_000;
let start = Instant::now();
for _ in 0..ITERATIONS {
for &input in &cases {
let _ = Dt::from_str_parse(input, &ParseCfg::DEFAULT);
}
}
let elapsed = start.elapsed();
let total_parses = cases.len() * ITERATIONS;
auto_ns_per = elapsed.as_nanos() as f64 / total_parses as f64;
}
{
const ITERATIONS: usize = 30_000_000;
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
const INPUT: &str = "2024-03-14T00:00:00";
use jiff::fmt::strtime::BrokenDownTime;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = BrokenDownTime::parse(FORMAT, INPUT).unwrap();
}
strptime_jiff_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = Parts::from_str(FORMAT, INPUT, true, true, false).unwrap();
}
strptime_timeparts_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
const ITERATIONS: usize = 10_000_000;
const INPUT: &str = "2024-03-14T00:00:00[America/New_York]";
const FORMAT_WITH_Q: &str = "%Y-%m-%dT%H:%M:%S[%Q]";
use jiff::fmt::strtime::BrokenDownTime;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let tm = BrokenDownTime::parse(FORMAT_WITH_Q, INPUT).unwrap();
let x = tm.to_zoned().unwrap();
}
zoned_jiff_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = Dt::from_str(INPUT, FORMAT_WITH_Q, true, true, false).unwrap();
}
zoned_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
const ITERATIONS: usize = 10_000_000; const INPUT: &str = "2024-03-14T00:00:00";
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
use jiff::fmt::strtime::BrokenDownTime;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let tm = BrokenDownTime::parse(FORMAT, INPUT).unwrap();
let x = tm.to_datetime().unwrap();
}
let _dt_strptime_jiff_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = Dt::from_str(INPUT, FORMAT, true, true, false).unwrap();
}
let _dt_strptime_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
const ITERATIONS: usize = 20_000_000;
const INPUT: &str = "2024-03-14T00:00:00.123456789";
use jiff::civil::DateTime;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = INPUT.parse::<DateTime>().unwrap();
}
iso_jiff_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = Parts::from_str_iso(INPUT).unwrap();
}
iso_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
{
const ITERATIONS: usize = 20_000_000;
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
let dt = Dt::from_str("2024-03-14T00:00:00", FORMAT, true, true, false).unwrap();
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = dt.to_str_lite(FORMAT, Lang::En);
}
strftime_deep_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
use jiff::civil::DateTime;
let jiff_dt: DateTime = "2024-03-14T00:00:00".parse().unwrap();
let start = std::time::Instant::now();
for _ in 0..ITERATIONS {
let x = jiff_dt.strftime(FORMAT).to_string();
}
strftime_jiff_ns = start.elapsed().as_nanos() as f64 / ITERATIONS as f64;
}
let fmt_ns = |x: f64| -> String {
if x >= 99.5 {
format!("{:.0} ns", x)
} else {
format!("{:.1} ns", x)
}
};
let pct = |d: f64, j: f64| -> String {
let r = d / j;
if r < 1.0 {
format!("{:.1}% faster", (1.0 - r) * 100.0)
} else {
format!("{:.1}% slower", (r - 1.0) * 100.0)
}
};
let xrel = |d: f64, h: f64| -> String {
let r = d / h;
if r < 1.0 {
format!("{:.1}× faster", 1.0 / r)
} else {
format!("{:.1}× slower", r)
}
};
eprintln!();
eprintln!("#### Parsing and Formatting");
eprintln!();
eprintln!(
"| Operation | Time | vs Jiff 0.2.31 |"
);
eprintln!(
"|----------------------------------------|---------------|--------------------------|"
);
eprintln!(
"| ISO datetime parsing | {:<13} | {:<24} |",
fmt_ns(iso_deep_ns),
pct(iso_deep_ns, iso_jiff_ns)
);
eprintln!(
"| `strptime` | {:<13} | {:<24} |",
fmt_ns(strptime_timeparts_ns),
pct(strptime_timeparts_ns, strptime_jiff_ns)
);
eprintln!(
"| TZ `strptime` -> `Dt` vs `jiff:Zoned` | {:<13} | {:<24} |",
fmt_ns(zoned_deep_ns),
pct(zoned_deep_ns, zoned_jiff_ns)
);
eprintln!(
"| `strftime` | {:<13} | {:<24} |",
fmt_ns(strftime_deep_ns),
pct(strftime_deep_ns, strftime_jiff_ns)
);
eprintln!(
"| Auto parser (`from_str_parse`) | {:<13} | — |",
fmt_ns(auto_ns_per)
);
eprintln!();
eprintln!("#### Time Scale Conversions");
eprintln!();
eprintln!(
"| Conversion | deep-time | hifitime 4.3 | Relative Performance |"
);
eprintln!(
"|------------------|---------------|---------------|---------------------------|"
);
eprintln!(
"| TAI → UTC | {:<13} | {:<13} | {:<25} |",
fmt_ns(tai_utc_deep_ns),
fmt_ns(tai_utc_hifi_ns),
xrel(tai_utc_deep_ns, tai_utc_hifi_ns)
);
eprintln!(
"| UTC → TAI | {:<13} | {:<13} | {:<25} |",
fmt_ns(utc_tai_deep_ns),
fmt_ns(utc_tai_hifi_ns),
xrel(utc_tai_deep_ns, utc_tai_hifi_ns)
);
eprintln!(
"| TAI → TDB | {:<13} | {:<13} | {:<25} |",
fmt_ns(tai_tdb_deep_ns),
fmt_ns(tai_tdb_hifi_ns),
xrel(tai_tdb_deep_ns, tai_tdb_hifi_ns)
);
eprintln!(
"| TDB → TAI | {:<13} | {:<13} | {:<25} |",
fmt_ns(tdb_tai_deep_ns),
fmt_ns(tdb_tai_hifi_ns),
xrel(tdb_tai_deep_ns, tdb_tai_hifi_ns)
);
eprintln!(
"| GPS conversion | {:<13} | {:<13} | {:<25} |",
fmt_ns(gps_deep_ns),
fmt_ns(gps_hifi_ns),
xrel(gps_deep_ns, gps_hifi_ns)
);
eprintln!(
"| GPS week + TOW | {:<13} | {:<13} | {:<25} |",
fmt_ns(tow_deep_ns),
fmt_ns(tow_hifi_ns),
xrel(tow_deep_ns, tow_hifi_ns)
);
eprintln!();
}
}