From ad6cb01fedced2815e30f2fe99e8a6cc31931023 Mon Sep 17 00:00:00 2001 From: Liu Dingming Date: Mon, 3 Mar 2025 02:09:34 +0800 Subject: [PATCH 1/5] Use criterion for benchmark --- Cargo.toml | 13 ++ benches/bench.rs | 246 ++++++++++++++++++----------- benches/insert_unique_unchecked.rs | 45 +++--- benches/set_ops.rs | 115 ++++++++------ 4 files changed, 251 insertions(+), 168 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c88df26e4..e89e62d66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ equivalent = { version = "1.0", optional = true, default-features = false } lazy_static = "1.4" rand = { version = "0.9.0", features = ["small_rng"] } rayon = "1.2" +criterion = "0.5" fnv = "1.0.7" serde_test = "1.0" doc-comment = "0.3.1" @@ -78,3 +79,15 @@ inline-more = [] [package.metadata.docs.rs] features = ["nightly", "rayon", "serde", "raw-entry"] rustdoc-args = ["--generate-link-to-definition"] + +[[bench]] +name = "bench" +harness = false + +[[bench]] +name = "insert_unique_unchecked" +harness = false + +[[bench]] +name = "set_ops" +harness = false diff --git a/benches/bench.rs b/benches/bench.rs index 111c5d54f..145ea4cd7 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -2,12 +2,8 @@ // Hasher: std default (SipHash) and crate default (foldhash). // Int key distribution: low bit heavy, top bit heavy, and random. // Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter -#![feature(test)] - -extern crate test; - -use test::{black_box, Bencher}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use hashbrown::DefaultHashBuilder; use hashbrown::{HashMap, HashSet}; use std::{ @@ -78,15 +74,16 @@ macro_rules! bench_suite { macro_rules! bench_insert { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { + fn $name(c: &mut Criterion) { let mut m = $maptype::with_capacity_and_hasher(SIZE, Default::default()); - b.iter(|| { - m.clear(); - for i in ($keydist).take(SIZE) { - m.insert(i, (DropType(i), [i; 20])); - } - black_box(&mut m); + c.bench_function(stringify!($name), |b| { + b.iter(|| { + m.clear(); + for i in ($keydist).take(SIZE) { + m.insert(i, (DropType(i), [i; 20])); + } + black_box(&mut m); + }); }); eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); } @@ -105,15 +102,16 @@ bench_suite!( macro_rules! bench_grow_insert { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - b.iter(|| { - let mut m = $maptype::default(); - for i in ($keydist).take(SIZE) { - m.insert(i, DropType(i)); - } - black_box(&mut m); - }) + fn $name(c: &mut Criterion) { + c.bench_function(stringify!($name), |b| { + b.iter(|| { + let mut m = $maptype::default(); + for i in ($keydist).take(SIZE) { + m.insert(i, DropType(i)); + } + black_box(&mut m); + }); + }); } }; } @@ -130,24 +128,25 @@ bench_suite!( macro_rules! bench_insert_erase { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { + fn $name(c: &mut Criterion) { let mut base = $maptype::default(); for i in ($keydist).take(SIZE) { base.insert(i, DropType(i)); } let skip = $keydist.skip(SIZE); - b.iter(|| { - let mut m = base.clone(); - let mut add_iter = skip.clone(); - let mut remove_iter = $keydist; - // While keeping the size constant, - // replace the first keydist with the second. - for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) { - m.insert(add, DropType(add)); - black_box(m.remove(&remove)); - } - black_box(m); + c.bench_function(stringify!($name), |b| { + b.iter(|| { + let mut m = base.clone(); + let mut add_iter = skip.clone(); + let mut remove_iter = $keydist; + // While keeping the size constant, + // replace the first keydist with the second. + for (add, remove) in (&mut add_iter).zip(&mut remove_iter).take(SIZE) { + m.insert(add, DropType(add)); + black_box(m.remove(&remove)); + } + black_box(m); + }); }); eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); } @@ -166,17 +165,18 @@ bench_suite!( macro_rules! bench_lookup { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { + fn $name(c: &mut Criterion) { let mut m = $maptype::default(); for i in $keydist.take(SIZE) { m.insert(i, DropType(i)); } - b.iter(|| { - for i in $keydist.take(SIZE) { - black_box(m.get(&i)); - } + c.bench_function(stringify!($name), |b| { + b.iter(|| { + for i in $keydist.take(SIZE) { + black_box(m.get(&i)); + } + }); }); eprintln!("{}", SIDE_EFFECT.load(atomic::Ordering::SeqCst)); } @@ -195,19 +195,20 @@ bench_suite!( macro_rules! bench_lookup_fail { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { + fn $name(c: &mut Criterion) { let mut m = $maptype::default(); let mut iter = $keydist; for i in (&mut iter).take(SIZE) { m.insert(i, DropType(i)); } - b.iter(|| { - for i in (&mut iter).take(SIZE) { - black_box(m.get(&i)); - } - }) + c.bench_function(stringify!($name), |b| { + b.iter(|| { + for i in (&mut iter).take(SIZE) { + black_box(m.get(&i)); + } + }); + }); } }; } @@ -224,18 +225,19 @@ bench_suite!( macro_rules! bench_iter { ($name:ident, $maptype:ident, $keydist:expr) => { - #[bench] - fn $name(b: &mut Bencher) { + fn $name(c: &mut Criterion) { let mut m = $maptype::default(); for i in ($keydist).take(SIZE) { m.insert(i, DropType(i)); } - b.iter(|| { - for i in &m { - black_box(i); - } - }) + c.bench_function(stringify!($name), |b| { + b.iter(|| { + for i in &m { + black_box(i); + } + }); + }); } }; } @@ -250,80 +252,132 @@ bench_suite!( iter_std_random ); -#[bench] -fn clone_small(b: &mut Bencher) { +fn clone_small(c: &mut Criterion) { let mut m = HashMap::new(); for i in 0..10 { m.insert(i, DropType(i)); } - b.iter(|| { - black_box(m.clone()); - }) + c.bench_function("clone_small", |b| { + b.iter(|| { + black_box(m.clone()); + }); + }); } -#[bench] -fn clone_from_small(b: &mut Bencher) { +fn clone_from_small(c: &mut Criterion) { let mut m = HashMap::new(); let mut m2 = HashMap::new(); for i in 0..10 { m.insert(i, DropType(i)); } - b.iter(|| { - m2.clone_from(&m); - black_box(&mut m2); - }) + c.bench_function("clone_from_small", |b| { + b.iter(|| { + m2.clone_from(&m); + black_box(&mut m2); + }); + }); } -#[bench] -fn clone_large(b: &mut Bencher) { +fn clone_large(c: &mut Criterion) { let mut m = HashMap::new(); for i in 0..1000 { m.insert(i, DropType(i)); } - b.iter(|| { - black_box(m.clone()); - }) + c.bench_function("clone_large", |b| { + b.iter(|| { + black_box(m.clone()); + }); + }); } -#[bench] -fn clone_from_large(b: &mut Bencher) { +fn clone_from_large(c: &mut Criterion) { let mut m = HashMap::new(); let mut m2 = HashMap::new(); for i in 0..1000 { m.insert(i, DropType(i)); } - b.iter(|| { - m2.clone_from(&m); - black_box(&mut m2); - }) + c.bench_function("clone_from_large", |b| { + b.iter(|| { + m2.clone_from(&m); + black_box(&mut m2); + }); + }); } -#[bench] -fn rehash_in_place(b: &mut Bencher) { - b.iter(|| { - let mut set = HashSet::new(); +fn rehash_in_place(c: &mut Criterion) { + c.bench_function("rehash_in_place", |b| { + b.iter(|| { + let mut set = HashSet::new(); - // Each loop triggers one rehash - for _ in 0..10 { - for i in 0..223 { - set.insert(i); - } + // Each loop triggers one rehash + for _ in 0..10 { + for i in 0..223 { + set.insert(i); + } - assert_eq!( - set.capacity(), - 224, - "The set must be at or close to capacity to trigger a re hashing" - ); + assert_eq!( + set.capacity(), + 224, + "The set must be at or close to capacity to trigger a rehashing" + ); - for i in 100..1400 { - set.remove(&(i - 100)); - set.insert(i); + for i in 100..1400 { + set.remove(&(i - 100)); + set.insert(i); + } + set.clear(); } - set.clear(); - } + }); }); } + +criterion_group!( + benches, + insert_foldhash_serial, + insert_std_serial, + insert_foldhash_highbits, + insert_std_highbits, + insert_foldhash_random, + insert_std_random, + grow_insert_foldhash_serial, + grow_insert_std_serial, + grow_insert_foldhash_highbits, + grow_insert_std_highbits, + grow_insert_foldhash_random, + grow_insert_std_random, + insert_erase_foldhash_serial, + insert_erase_std_serial, + insert_erase_foldhash_highbits, + insert_erase_std_highbits, + insert_erase_foldhash_random, + insert_erase_std_random, + lookup_foldhash_serial, + lookup_std_serial, + lookup_foldhash_highbits, + lookup_std_highbits, + lookup_foldhash_random, + lookup_std_random, + lookup_fail_foldhash_serial, + lookup_fail_std_serial, + lookup_fail_foldhash_highbits, + lookup_fail_std_highbits, + lookup_fail_foldhash_random, + lookup_fail_std_random, + iter_foldhash_serial, + iter_std_serial, + iter_foldhash_highbits, + iter_std_highbits, + iter_foldhash_random, + iter_std_random, + clone_small, + clone_from_small, + clone_large, + clone_from_large, + rehash_in_place +); + +criterion_main!(benches); diff --git a/benches/insert_unique_unchecked.rs b/benches/insert_unique_unchecked.rs index cfd69cdb7..300ff66a6 100644 --- a/benches/insert_unique_unchecked.rs +++ b/benches/insert_unique_unchecked.rs @@ -1,34 +1,35 @@ //! Compare `insert` and `insert_unique_unchecked` operations performance. -#![feature(test)] - -extern crate test; - +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use hashbrown::HashMap; -use test::Bencher; -#[bench] -fn insert(b: &mut Bencher) { +fn insert_benchmark(c: &mut Criterion) { let keys: Vec = (0..1000).map(|i| format!("xxxx{}yyyy", i)).collect(); - b.iter(|| { - let mut m = HashMap::with_capacity(1000); - for k in &keys { - m.insert(k, k); - } - m + c.bench_function("insert", |b| { + b.iter(|| { + let mut m = HashMap::with_capacity(1000); + for k in &keys { + m.insert(black_box(k), black_box(k)); + } + m + }); }); } -#[bench] -fn insert_unique_unchecked(b: &mut Bencher) { +fn insert_unique_unchecked_benchmark(c: &mut Criterion) { let keys: Vec = (0..1000).map(|i| format!("xxxx{}yyyy", i)).collect(); - b.iter(|| { - let mut m = HashMap::with_capacity(1000); - for k in &keys { - unsafe { - m.insert_unique_unchecked(k, k); + c.bench_function("insert_unique_unchecked", |b| { + b.iter(|| { + let mut m = HashMap::with_capacity(1000); + for k in &keys { + unsafe { + m.insert_unique_unchecked(black_box(k), black_box(k)); + } } - } - m + m + }); }); } + +criterion_group!(benches, insert_benchmark, insert_unique_unchecked_benchmark); +criterion_main!(benches); diff --git a/benches/set_ops.rs b/benches/set_ops.rs index 3b2ab5f28..a9dbc67c3 100644 --- a/benches/set_ops.rs +++ b/benches/set_ops.rs @@ -5,12 +5,8 @@ //! Each assigning test is done in the configuration that is faster. Cheating, I know. //! The exception to this is Sub, because there the result differs. So I made two benchmarks for Sub. -#![feature(test)] - -extern crate test; - +use criterion::{criterion_group, criterion_main, Criterion}; use hashbrown::HashSet; -use test::Bencher; /// The number of items to generate for the larger of the sets. const LARGE_SET_SIZE: usize = 1000; @@ -27,122 +23,141 @@ fn create_set(start: usize, end: usize) -> HashSet { (start..end).map(|nr| format!("key{}", nr)).collect() } -#[bench] -fn set_ops_bit_or(b: &mut Bencher) { +fn set_ops_bit_or(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| &large_set | &small_set) + c.bench_function("set_ops_bit_or", |b| b.iter(|| &large_set | &small_set)); } -#[bench] -fn set_ops_bit_and(b: &mut Bencher) { +fn set_ops_bit_and(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| &large_set & &small_set) + c.bench_function("set_ops_bit_and", |b| b.iter(|| &large_set & &small_set)); } -#[bench] -fn set_ops_bit_xor(b: &mut Bencher) { +fn set_ops_bit_xor(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| &large_set ^ &small_set) + c.bench_function("set_ops_bit_xor", |b| b.iter(|| &large_set ^ &small_set)); } -#[bench] -fn set_ops_sub_large_small(b: &mut Bencher) { +fn set_ops_sub_large_small(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| &large_set - &small_set) + c.bench_function("set_ops_sub_large_small", |b| { + b.iter(|| &large_set - &small_set) + }); } -#[bench] -fn set_ops_sub_small_large(b: &mut Bencher) { +fn set_ops_sub_small_large(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| &small_set - &large_set) + c.bench_function("set_ops_sub_small_large", |b| { + b.iter(|| &small_set - &large_set) + }); } -#[bench] -fn set_ops_bit_or_assign(b: &mut Bencher) { +fn set_ops_bit_or_assign(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| { - let mut set = large_set.clone(); - set |= &small_set; - set + c.bench_function("set_ops_bit_or_assign", |b| { + b.iter(|| { + let mut set = large_set.clone(); + set |= &small_set; + set + }); }); } -#[bench] -fn set_ops_bit_and_assign(b: &mut Bencher) { +fn set_ops_bit_and_assign(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| { - let mut set = small_set.clone(); - set &= &large_set; - set + c.bench_function("set_ops_bit_and_assign", |b| { + b.iter(|| { + let mut set = small_set.clone(); + set &= &large_set; + set + }); }); } -#[bench] -fn set_ops_bit_xor_assign(b: &mut Bencher) { +fn set_ops_bit_xor_assign(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| { - let mut set = large_set.clone(); - set ^= &small_set; - set + c.bench_function("set_ops_bit_xor_assign", |b| { + b.iter(|| { + let mut set = large_set.clone(); + set ^= &small_set; + set + }); }); } -#[bench] -fn set_ops_sub_assign_large_small(b: &mut Bencher) { +fn set_ops_sub_assign_large_small(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| { - let mut set = large_set.clone(); - set -= &small_set; - set + c.bench_function("set_ops_sub_assign_large_small", |b| { + b.iter(|| { + let mut set = large_set.clone(); + set -= &small_set; + set + }); }); } -#[bench] -fn set_ops_sub_assign_small_large(b: &mut Bencher) { +fn set_ops_sub_assign_small_large(c: &mut Criterion) { let large_set = create_set(0, LARGE_SET_SIZE); let small_set = create_set( LARGE_SET_SIZE - OVERLAP, LARGE_SET_SIZE + SMALL_SET_SIZE - OVERLAP, ); - b.iter(|| { - let mut set = small_set.clone(); - set -= &large_set; - set + c.bench_function("set_ops_sub_assign_small_large", |b| { + b.iter(|| { + let mut set = small_set.clone(); + set -= &large_set; + set + }); }); } + +criterion_group!( + benches, + set_ops_bit_or, + set_ops_bit_and, + set_ops_bit_xor, + set_ops_sub_large_small, + set_ops_sub_small_large, + set_ops_bit_or_assign, + set_ops_bit_and_assign, + set_ops_bit_xor_assign, + set_ops_sub_assign_large_small, + set_ops_sub_assign_small_large +); +criterion_main!(benches); From 9a9b73a479b9a65eacdf6bab65d63dc23a6838dd Mon Sep 17 00:00:00 2001 From: Liu Dingming Date: Mon, 3 Mar 2025 03:02:32 +0800 Subject: [PATCH 2/5] Update `rayon` requirement from `1.2` to `1.3` --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e89e62d66..db269cfa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ rust-version = "1.65.0" foldhash = { version = "0.1.2", default-features = false, optional = true } # For external trait impls -rayon = { version = "1.2", optional = true } +rayon = { version = "1.3", optional = true } serde = { version = "1.0.25", default-features = false, optional = true } # When built as part of libstd @@ -36,8 +36,8 @@ equivalent = { version = "1.0", optional = true, default-features = false } [dev-dependencies] lazy_static = "1.4" rand = { version = "0.9.0", features = ["small_rng"] } -rayon = "1.2" -criterion = "0.5" +rayon = "1.3" +criterion = "0.5.1" fnv = "1.0.7" serde_test = "1.0" doc-comment = "0.3.1" From 769ed9b144e5fdcbba8d736475845bd1e0d9f2c5 Mon Sep 17 00:00:00 2001 From: Liu Dingming Date: Tue, 11 Mar 2025 21:50:13 +0800 Subject: [PATCH 3/5] Update MSRV to 1.74.0 --- .github/workflows/rust.yml | 2 +- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- README.md | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0d52bec22..8aecc3184 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -82,7 +82,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - - uses: dtolnay/rust-toolchain@1.65.0 # MSRV + - uses: dtolnay/rust-toolchain@1.74.0 # MSRV - run: cargo +nightly generate-lockfile -Z direct-minimal-versions - env: TARGET: x86_64-unknown-linux-gnu diff --git a/CHANGELOG.md b/CHANGELOG.md index ea702c384..bfbc0e5c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +### Changed + +- Relaxed MSRV to 1.74.0. (#609) + ## [v0.15.2] - 2024-11-14 ### Added diff --git a/Cargo.toml b/Cargo.toml index db269cfa9..ff5f5c622 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["hash", "no_std", "hashmap", "swisstable"] categories = ["data-structures", "no-std"] exclude = [".github", "/ci/*"] edition = "2021" -rust-version = "1.65.0" +rust-version = "1.74.0" [dependencies] # For the default hasher diff --git a/README.md b/README.md index 83a538115..69ad60425 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ hashbrown [![Build Status](https://github.com/rust-lang/hashbrown/actions/workflows/rust.yml/badge.svg)](https://github.com/rust-lang/hashbrown/actions) [![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown) [![Documentation](https://docs.rs/hashbrown/badge.svg)](https://docs.rs/hashbrown) -[![Rust](https://img.shields.io/badge/rust-1.65.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown) +[![Rust](https://img.shields.io/badge/rust-1.74.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown) This crate is a Rust port of Google's high-performance [SwissTable] hash map, adapted to make it a drop-in replacement for Rust's standard `HashMap` From 659fffd53dacac4254ec1eb43f5758359bc399b0 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Tue, 11 Mar 2025 22:40:47 +0800 Subject: [PATCH 4/5] Fix clippy --- src/external_trait_impls/rayon/map.rs | 4 ++-- src/external_trait_impls/rayon/set.rs | 2 +- src/map.rs | 9 +++------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/external_trait_impls/rayon/map.rs b/src/external_trait_impls/rayon/map.rs index 9623ca747..e12080d0d 100644 --- a/src/external_trait_impls/rayon/map.rs +++ b/src/external_trait_impls/rayon/map.rs @@ -346,7 +346,7 @@ where self.len() == other.len() && self .into_par_iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) + .all(|(key, value)| other.get(key).is_some_and(|v| *value == *v)) } } @@ -455,7 +455,7 @@ where // Reserve the entire length if the map is empty. // Otherwise reserve half the length (rounded up), so the map // will only resize twice in the worst case. - let reserve = if map.is_empty() { len } else { (len + 1) / 2 }; + let reserve = if map.is_empty() { len } else { len.div_ceil(2) }; map.reserve(reserve); for vec in list { map.extend(vec); diff --git a/src/external_trait_impls/rayon/set.rs b/src/external_trait_impls/rayon/set.rs index 3de98fccb..8a3bfa481 100644 --- a/src/external_trait_impls/rayon/set.rs +++ b/src/external_trait_impls/rayon/set.rs @@ -384,7 +384,7 @@ where // Reserve the entire length if the set is empty. // Otherwise reserve half the length (rounded up), so the set // will only resize twice in the worst case. - let reserve = if set.is_empty() { len } else { (len + 1) / 2 }; + let reserve = if set.is_empty() { len } else { len.div_ceil(2) }; set.reserve(reserve); for vec in list { set.extend(vec); diff --git a/src/map.rs b/src/map.rs index 63700204a..dcd0bb3fa 100644 --- a/src/map.rs +++ b/src/map.rs @@ -242,10 +242,7 @@ where Q: Hash + ?Sized, S: BuildHasher, { - use core::hash::Hasher; - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() + hash_builder.hash_one(val) } #[cfg(feature = "nightly")] @@ -2022,7 +2019,7 @@ where } self.iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) + .all(|(key, value)| other.get(key).is_some_and(|v| *value == *v)) } } @@ -4493,7 +4490,7 @@ where let reserve = if self.is_empty() { iter.size_hint().0 } else { - (iter.size_hint().0 + 1) / 2 + iter.size_hint().0.div_ceil(2) }; self.reserve(reserve); iter.for_each(move |(k, v)| { From fd8170d1040da110b2375f505b2c6a811571adad Mon Sep 17 00:00:00 2001 From: ldm0 Date: Tue, 11 Mar 2025 23:19:26 +0800 Subject: [PATCH 5/5] Update serde to 1.0.103 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ff5f5c622..05ffc052f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ foldhash = { version = "0.1.2", default-features = false, optional = true } # For external trait impls rayon = { version = "1.3", optional = true } -serde = { version = "1.0.25", default-features = false, optional = true } +serde = { version = "1.0.103", default-features = false, optional = true } # When built as part of libstd core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }