Skip to content

Conversation

@Veykril
Copy link
Member

@Veykril Veykril commented Jan 5, 2025

Additionally newtypes these maps.

We got no reason to hash what we already have hashed! (This does need hashbrown as std doesn't stably expose the required API yet)

@netlify
Copy link

netlify bot commented Jan 5, 2025

Deploy Preview for salsa-rs canceled.

Name Link
🔨 Latest commit 049cb14
🔍 Latest deploy log https://app.netlify.com/sites/salsa-rs/deploys/67935295b7da8a00088996f5

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 5, 2025

CodSpeed Performance Report

Merging #647 will not alter performance

Comparing Veykril:veykril/push-tqxotywkkxky (049cb14) with master (855a31a)

Summary

✅ 9 untouched benchmarks

@Veykril Veykril force-pushed the veykril/push-tqxotywkkxky branch from 51cdd70 to 67e8cab Compare January 5, 2025 11:44
@MichaReiser
Copy link
Contributor

Did you do any perf measurements on ra to verify that the extra complexity and memory usage is worth it?

@Veykril
Copy link
Member Author

Veykril commented Jan 5, 2025

Not yet, until r-a can use the master branch salsa, checking anything against r-a is kind of a pain as I'd need to work against david's fork I believe.

Either way I'd consider the complexity here rather minor and self-contained (I can clean it up a bit and make it more descriptive if desired) while omitting unnecessary work. So even with perf measurement it should be clear that this skips work imo

@Veykril Veykril force-pushed the veykril/push-tqxotywkkxky branch from 1637c61 to d717cf8 Compare January 23, 2025 12:32
Comment on lines 156 to 159
// conceptually, this contains an `IdentityHash`, but using the type directly will grow the size
// of if this struct by a word due to unusable padding, so we store the fields directly instead.
/// Index of the tracked struct ingredient.
Copy link
Contributor

Choose a reason for hiding this comment

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

two nits:

  • Phrasing
  • Considering moving this comment up to Identity's doc comment?
Suggested change
// conceptually, this contains an `IdentityHash`, but using the type directly will grow the size
// of if this struct by a word due to unusable padding, so we store the fields directly instead.
/// Index of the tracked struct ingredient.
/// Index of the tracked struct ingredient.
///
/// Conceptually, this contains an `IdentityHash`, but using `IdentityHash` directly will grow the size
/// of this struct struct by a `std::mem::size_of::<usize>()` due to unusable padding. To avoid this increase
/// in size, `Identity` stores the fields directly instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

I put it outside of the doc comment as this is just an implementation detail, it is not relevant to the ingredient_index field

Copy link
Contributor

@davidbarsky davidbarsky left a comment

Choose a reason for hiding this comment

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

looks good to me, modulo documentation and style nits.

Comment on lines 211 to 214
let eq_module_hash = |k: &Identity| {
k.ingredient_index == key.ingredient_index && k.disambiguator == key.disambiguator
};
let entry = self.map.raw_entry_mut().from_hash(key.hash, eq_module_hash);
Copy link
Contributor

Choose a reason for hiding this comment

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

consider inlining eq_module_hash?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, that was supposed to be eq_modulo_hash. I prefer keeping it outside as it documents what we check (also the formatting like this is more readable imo)

Comment on lines 225 to 228
let eq_module_hash = |k: &Identity| {
k.ingredient_index == key.ingredient_index && k.disambiguator == key.disambiguator
};
Copy link
Contributor

Choose a reason for hiding this comment

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

consider inlining eq_module_hash?

Comment on lines 307 to 308
let eq_module_hash = |k: &IdentityHash| k.ingredient_index == key.ingredient_index;
let entry = self.map.raw_entry_mut().from_hash(key.hash, eq_module_hash);
Copy link
Contributor

Choose a reason for hiding this comment

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

consider inlining eq_module_hash?

@Veykril Veykril force-pushed the veykril/push-tqxotywkkxky branch from d717cf8 to 049cb14 Compare January 24, 2025 08:42
@Veykril Veykril added this pull request to the merge queue Jan 24, 2025
Merged via the queue into salsa-rs:master with commit cde9fbd Jan 24, 2025
10 checks passed
@MichaReiser
Copy link
Contributor

Backing out of this PR fixes the coarse grained dependency upgrade in Ruff. I've to take a look at this more closely tomorrow

@Veykril
Copy link
Member Author

Veykril commented Feb 8, 2025

That sounds surprising to me as this PR shouldn't have changed anything.

pub(crate) fn disambiguate(&mut self, key: IdentityHash) -> Disambiguator {
use hashbrown::hash_map::RawEntryMut;

let eq_modulo_hash = |k: &IdentityHash| k.ingredient_index == key.ingredient_index;
Copy link
Contributor

@MichaReiser MichaReiser Feb 8, 2025

Choose a reason for hiding this comment

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

It seems that we also need to include k.hash == key.hash.... I assume that is because the hash map might map multiple hashes to the same bucket and it then uses the equality function to disambiguate. This applies here and at the other from_hash call sites.

What's good about it is that it simplifies the eq implementation a lot :)

Copy link
Member

Choose a reason for hiding this comment

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

To add a little context, hashbrown doesn't store a full hash of each key, and only compares partially. The equality function cannot rely on the hash being equal, it must uniquely identify an entry regardless (e.g. hashbrown could legally do a linear search for equality).

Copy link
Member Author

@Veykril Veykril Feb 9, 2025

Choose a reason for hiding this comment

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

Ah I see, well that would do it. I completely forgot that hashmaps tend to trim the hash to pick a bucket to put the values into... I hope that didn't waste too much time sorry.

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.

4 participants