Skip to content

Commit

Permalink
Replace macro unwrap!() with const fn (#179)
Browse files Browse the repository at this point in the history
* Replace macro `unwrap!()` with `const fn`

The library compiles quite a lot faster this way.

* Pin `regex`

* Move `fuzz` into its own workspace

* Fix pedantic warnings

* Update to 2023c

* Update changelog

* bench: Use `xoroshiro128++` instead of `SmallRng`

The algo used in `SmallRng` not fixed, so it could be that different
inputs get benchmarked, making the result useless.

Also `SmallRng` does not like seeds with little popcounts. Since our
seeds are something like `0..100`, this is not quite optimal.

* Move benchmarks into their own workspace

This way its many dependencies won't turn up in the library's
`Cargo.toml`, so I can unpin many pinned dependencies, and still comply
with our msrv.
  • Loading branch information
Kijewski authored May 11, 2023
1 parent d5231f7 commit 48fb605
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 114 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Changes between the versions

### 0.5.7 (2023-05-11)

* Fewer macros = faster compile times
* Update to Time Zone Database release [2023c](https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html)

### 0.5.6 (2023-03-24)

* Update to Time Zone Database release [2023b](https://mm.icann.org/pipermail/tz-announce/2023-March/000078.html)
Expand Down
18 changes: 1 addition & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tzdb"
version = "0.5.6"
version = "0.5.7"
edition = "2018"
authors = ["René Kijewski <crates.io@k6i.de>"]
repository = "https://github.com/Kijewski/tzdb"
Expand All @@ -16,31 +16,16 @@ tz-rs = { version = "^0.6.14", default-features = false, features = ["const", "s
iana-time-zone = { version = "^0.1.50", default-features = false }

[dev-dependencies]
criterion = { version = "^0.3.6", default-features = false }
proptest = "=1.0"
rand = { version = "^0.8.5", default-features = false, features = ["std", "small_rng"] }
test-strategy = "=0.1.2"
structmeta = "=0.1.4"

# 1.15 is edition 2021, used (transitively) by criterion
once_cell = "=1.14"
# 1.2 is edition 2021, used (transitively) by criterion
csv = "=1.1"
# 1.7 has rust-version = "1.59", used (transitively) by criterion
rayon = "=1.6"
# 1.11 has rust-version = "1.59", used (transitively) by criterion
rayon-core = "=1.10"

[features]
default = ["fallback"]

# Do not fail to compile for unknown target platforms:
fallback = ["iana-time-zone/fallback"]

[[bench]]
name = "by-name"
harness = false

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
Expand All @@ -50,5 +35,4 @@ members = [
".",
"examples/current-time",
"make-tzdb",
"fuzz",
]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.DELETE_ON_ERROR:

TZDB_VERSION := tzdb-2023b
TZDB_VERSION := tzdb-2023c

src/generated/mod.rs: tmp/${TZDB_VERSION}/usr/share/zoneinfo/
cargo r --package make-tzdb --bin make-tzdb -- $(@D) $< tzdb.tar.lz.sha
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Static time zone information for [tz-rs](https://crates.io/crates/tz-rs).

This crate provides all time zones found in the [Time Zone Database](https://www.iana.org/time-zones),
currently in the version 2023b (released 2023-03-23).
currently in the version 2023c (released 2023-03-28).

See the documentation for a full list the the contained time zones:
<https://docs.rs/tzdb/latest/tzdb/time_zone/index.html>
Expand Down
27 changes: 27 additions & 0 deletions benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "tzdb-bench"
version = "0.0.0"
edition = "2021"
authors = ["René Kijewski <crates.io@k6i.de>"]
repository = "https://github.com/Kijewski/tzdb"
description = "… benchmarking …"
license = "Apache-2.0"
# rust-version = "1.56"
publish = false

[dependencies]
tzdb = { version = "*", path = ".." }

[dev-dependencies]
criterion = { version = "0.4.0", default-features = false }
rand = { version = "0.8.5", default-features = false, features = ["std"] }
rand_xoshiro = "0.6.0"
test-strategy = "0.3.0"
structmeta = "0.2.0"

[[bench]]
name = "by-name"
harness = false

[workspace]
members = ["."]
6 changes: 3 additions & 3 deletions benches/by-name.rs → benchmarks/benches/by-name.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::convert::TryInto;
use std::time::{Duration, Instant};

use rand::rngs::SmallRng;
use rand::seq::{IteratorRandom, SliceRandom};
use rand::SeedableRng;
use rand_xoshiro::Xoroshiro128PlusPlus;
use tzdb::{raw_tz_by_name, TZ_NAMES};

fn benchmark_by_name(c: &mut criterion::Criterion) {
Expand Down Expand Up @@ -57,7 +57,7 @@ fn benchmark_by_name(c: &mut criterion::Criterion) {

// insert a bunch of unknown names
for idx in 0..100 {
let mut rng = SmallRng::seed_from_u64(idx);
let mut rng = Xoroshiro128PlusPlus::seed_from_u64(idx);

let mut continent = *b"abcdefghijklmnopqrstuvwxyz";
let mut city = *b"abcdefghijklmnopqrstuvwxyz";
Expand All @@ -84,7 +84,7 @@ fn benchmark_by_name(c: &mut criterion::Criterion) {
b.iter_custom(|iters| {
let mut nanos = 0;
for i in 0..iters {
names.shuffle(&mut SmallRng::seed_from_u64(i));
names.shuffle(&mut Xoroshiro128PlusPlus::seed_from_u64(i));

let start = Instant::now();
let names = criterion::black_box(&*names);
Expand Down
3 changes: 3 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ path = "bin/libfuzzer.rs"
test = false
doc = false
required-features = ["libfuzzer-sys"]

[workspace]
members = ["."]
105 changes: 81 additions & 24 deletions make-tzdb/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,86 @@ pub fn main() -> anyhow::Result<()> {
mod test_all_names;
pub(crate) mod by_name;
use tz::TimeZoneRef;
macro_rules! unwrap {{
($($tt:tt)*) => {{
match $($tt)* {{
Ok(value) => value,
Err(_) => {{
#[allow(unconditional_panic)]
let err = [][0];
err
}}
}}
pub(crate) const VERSION: &str = {version:?};
pub(crate) const VERSION_HASH: &str = {hash:?};
pub(crate) const fn new_time_zone_ref(
transitions: &'static [tz::timezone::Transition],
local_time_types: &'static [tz::LocalTimeType],
leap_seconds: &'static [tz::timezone::LeapSecond],
extra_rule: &'static Option<tz::timezone::TransitionRule>,
) -> tz::timezone::TimeZoneRef<'static> {{
match tz::timezone::TimeZoneRef::new(transitions, local_time_types, leap_seconds, extra_rule) {{
Ok(value) => value,
Err(_) => {{
#[allow(unconditional_panic)]
let err = [][0];
err
}},
}}
}}
pub(crate) use unwrap;
pub(crate) const VERSION: &str = {version:?};
pub(crate) const VERSION_HASH: &str = {hash:?};
pub(crate) const fn new_local_time_type(
ut_offset: i32,
is_dst: bool,
time_zone_designation: Option<&[u8]>,
) -> tz::LocalTimeType {{
match tz::LocalTimeType::new(ut_offset, is_dst, time_zone_designation) {{
Ok(value) => value,
Err(_) => {{
#[allow(unconditional_panic)]
let err = [][0];
err
}},
}}
}}
pub(crate) const fn new_transition(
unix_leap_time: i64,
local_time_type_index: usize,
) -> tz::timezone::Transition {{
tz::timezone::Transition::new(unix_leap_time, local_time_type_index)
}}
pub(crate) const fn new_alternate_time(
std: tz::LocalTimeType,
dst: tz::LocalTimeType,
dst_start: tz::timezone::RuleDay,
dst_start_time: i32,
dst_end: tz::timezone::RuleDay,
dst_end_time: i32,
) -> tz::timezone::AlternateTime {{
match tz::timezone::AlternateTime::new(
std,
dst,
dst_start,
dst_start_time,
dst_end,
dst_end_time,
) {{
Ok(value) => value,
Err(_) => {{
#[allow(unconditional_panic)]
let err = [][0];
err
}},
}}
}}
pub(crate) const fn new_month_week_day(
month: u8,
week: u8,
week_day: u8,
) -> tz::timezone::MonthWeekDay {{
match tz::timezone::MonthWeekDay::new(month, week, week_day) {{
Ok(value) => value,
Err(_) => {{
#[allow(unconditional_panic)]
let err = [][0];
err
}},
}}
}}
"#
)?;

Expand Down Expand Up @@ -369,34 +431,29 @@ pub(crate) const VERSION_HASH: &str = {hash:?};
// all known time zones as reference to (raw_)tzdata
writeln!(f, "/// All defined time zones statically accessible")?;
writeln!(f, "pub mod time_zone {{")?;
writeln!(f, " use super::*;")?;
for (folder, entries) in &entries_by_major {
writeln!(f)?;
if let Some(folder) = folder {
writeln!(f, "/// {}", folder)?;
writeln!(f, "pub mod {} {{", folder)?;
writeln!(f, " use super::*;")?;
}
for entry in entries {
writeln!(f)?;
writeln!(f, " /// Time zone data for {},", entry.full)?;
writeln!(
f,
"pub const {}: TimeZoneRef<'static> = tzdata::{};",
"pub const {}: tz::TimeZoneRef<'static> = crate::generated::tzdata::{};",
entry.minor, entry.canon,
)?;
}

for entry in entries {
writeln!(f)?;
writeln!(
f,
" /// Raw, unparsed time zone data for {},",
entry.full
)?;
writeln!(
f,
"pub const RAW_{}: &[u8] = raw_tzdata::{};",
"pub const RAW_{}: &[u8] = crate::generated::raw_tzdata::{};",
entry.minor, entry.canon,
)?;
}
Expand Down Expand Up @@ -436,9 +493,9 @@ pub(crate) const VERSION_HASH: &str = {hash:?};
writeln!(f)?;
writeln!(
f,
"pub(crate) const {}: TimeZoneRef<'static> = {};",
"pub(crate) const {}: tz::TimeZoneRef<'static> = {};",
&entries[0].canon,
parse::Unwrap(&tz_convert(bytes)),
tz_convert(bytes),
)?;
}
writeln!(f, "}}")?;
Expand Down
Loading

0 comments on commit 48fb605

Please sign in to comment.