Skip to content

Allow alternative hash functions in GraphMap#622

Merged
ABorgna merged 1 commit intopetgraph:masterfrom
daniel-levin:master
Apr 1, 2024
Merged

Allow alternative hash functions in GraphMap#622
ABorgna merged 1 commit intopetgraph:masterfrom
daniel-levin:master

Conversation

@daniel-levin
Copy link
Copy Markdown
Contributor

Hi there @bluss and @ABorgna!

Today, GraphMap uses IndexMap's default choice of hash function. Like many Rustaceans, I have a use case that is bottlenecked by hashing, which could take advantage of a faster hash function.

This change allows users of this crate to pick alternative hashers, as they might with an IndexMap or a HashMap, but only if they want to. Existing code will still work, because each impl has been made more generic, since std::hash::RandomState already implements BuildHasher and Default.

I took dev-dependencies on ahash and fxhash, and extended a benchmark I'd previously contributed:

running 3 tests
test graphmap_serial_bench        ... bench: 208,458,239 ns/iter (+/- 6,845,112)
test graphmap_serial_bench_ahash  ... bench: 171,139,041 ns/iter (+/- 3,972,136)
test graphmap_serial_bench_fxhash ... bench: 183,217,281 ns/iter (+/- 55,096,481)

@daniel-levin daniel-levin force-pushed the master branch 6 times, most recently from 3e81e1c to 8e40f11 Compare March 25, 2024 07:37
Copy link
Copy Markdown
Member

@ABorgna ABorgna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. Thanks!

@ABorgna ABorgna merged commit c71f6e4 into petgraph:master Apr 1, 2024
pub fn new() -> Self
where
S: Default,
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: by leaving S open here, it means that type inference can't figure it out, and it won't use the default either. e.g. This used to work:

let mut graph = GraphMap::new();
// ... other code that insert stuff, inferring those types but *not* the hasher

Now to allow inference I have to write:

let mut graph = GraphMap::<_, _, _>::new(); // now 4th param `S` is defaulted

That's why HashMap::new() and IndexMap::new() only use the default hasher, while default() is fully generic.
See also: https://faultlore.com/blah/defaults-affect-inference/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't get me wrong, this is a great feature overall! I would have just left new() on the old hasher for the reason above, but it would be a breaking change to go back on that now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, thanks for the comment. I would have done it differently if I'd realized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants