Skip to content

Avoid hashing more than is strictly necessary, in the compiler. #56308

Open

Description

@eddyb

It should be possible to build cheaper interners than what we currently have, using raw_entry.
cc @rust-lang/compiler @gankro @Amanieu

Activity

  1. Zoxc commented on Nov 28, 2018

    @Zoxc
    Contributor

    I have a branch which adds functions for interning based on this PR. I suggest that further work be based on that.

    cc @nnethercote

    Also relevant #55514 #56241

  2. eddyb commented on Nov 28, 2018

    @eddyb
    ContributorAuthor

    @Zoxc That is, change the implementation of the HashSetInterner trait to use the new APIs?
    That seems good, and I'd even call the abstraction HashingInterner, InternByHash or something similar (since the "set" aspect is less relevant than the fact that this is based on hashing).

  3. Zoxc commented on Nov 28, 2018

    @Zoxc
    Contributor

    Sure. I think we have to change things to use a HashMap anyway. HashSet hides all the fun bits.

  4. eddyb commented on Nov 28, 2018

    @eddyb
    ContributorAuthor

    Oh, another place where we could take advantage of computing the hash only once is the query engine, in case we had to compute a query, and we're inserting the result.

  5. michaelwoerister commented on Nov 29, 2018

    @michaelwoerister
    Member

    Another note, not directly related to interners: We have some things in the compiler that already contain high-quality hash values of themselves. E.g. it's unnecessary work to hash a DefPathHash. There's at least one such map here:

    pub def_path_hash_to_def_id: Option<FxHashMap<DefPathHash, DefId>>,

    There are probably a few additional, similar cases.

  6. eddyb commented on Nov 29, 2018

    @eddyb
    ContributorAuthor

    @michaelwoerister I think we can maybe use a wrapper for the hash state that uses specialization to avoid double-hashing, in that case, instead of relying on raw_entry.

  7. michaelwoerister commented on Nov 29, 2018

    @michaelwoerister
    Member

    I think the raw_entry API would be the nicer way to do it. It seems to be tailored to support a case just like this (among other use cases).

  8. eddyb commented on Nov 29, 2018

    @eddyb
    ContributorAuthor

    @michaelwoerister Yes but it would require making an entire wrapper of the HashMap public API which carefully avoids letting anything hash the key (going as far as wrapping the key in a type that panics in its Hash impl).

  9. michaelwoerister commented on Nov 29, 2018

    @michaelwoerister
    Member

    What would your solution look like?

  10. added a commit that references this issue on Nov 30, 2018
  11. 1 remaining item

  12. eddyb commented on Dec 2, 2018

    @eddyb
    ContributorAuthor

    I'll reopen this because the discussion mentioned things other than interners.

    Also, I still have to write those code examples for @michaelwoerister.

  13. reopened this on Dec 2, 2018
  14. added
    C-cleanupCategory: PRs that clean code up or issues documenting cleanup.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jan 27, 2019
  15. Noratrieb commented on May 10, 2023

    @Noratrieb
    Member

    The interners currently do use the raw entry APIs:

    let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value);

  16. oli-obk commented on May 11, 2023

    @oli-obk
    Contributor

    We should still look for other uses of hash maps with keys that are already hashes

  17. added a commit that references this issue on Jan 17, 2024
  18. Mark-Simulacrum commented on Jan 18, 2024

    @Mark-Simulacrum
    Member

    I ran some analysis to find the maps changed in #120076 by looking for things put into HashMaps that looked like they were already hashes, using a few heuristics (e.g., similar number of 1 and 0 bits). I think that found most or all of the problem places. I don't see a good way to assert we don't regress there -- with a TypeId for non 'static things, we could assert in Hash64/Hash128 etc impls that we're not hashing them with FxHash (or that we're only hashing them with Unhash). But that assert doesn't exist today, and I don't think adding e.g. specialization or a doc(hidden) method on Hasher in std makes sense for this at this time.

    I think the next big opportunity for reducing hashing would be maps with dense, relatively small integer valued keys, where we actually don't need to hash because they're sufficiently dense that a vec makes more sense. We saw big wins with #119977 from both (a) removing the hashing and (b) improved cache locality due to keeping things closer together. But those typically aren't as easy of a transformation to make, and to some extent are a time/space tradeoff.

  19. added 3 commits that reference this issue on Jan 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-cleanupCategory: PRs that clean code up or issues documenting cleanup.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions