Skip to content

Introduce set with custom equals and getHashCode #48169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 12, 2022

Conversation

amcasey
Copy link
Member

@amcasey amcasey commented Mar 8, 2022

I got tired of not having custom hash sets in JS so I made a naive one.

Not using linear search to de-dup rename locations cuts search for locations of Type from 1750 ms to 1450 ms.

I plan to use this in a bunch of other places in my FAR cleanup.

TODO: this is the simplest possible implementation
TODO: these were the consumers that I'd encountered recently

@typescript-bot typescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Mar 8, 2022
@amcasey amcasey requested review from weswigham, andrewbranch and sandersn and removed request for andrewbranch March 8, 2022 00:35
Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

This seems like a reasonable thing to have, although I'm tempted to say it should be in src/server since it's used only there. Probably having it in a central place is more valuable though.

@andrewbranch
Copy link
Member

Do you have a sense of how often you expect entries in the set to share a hash? If best practice is for hashes to be unique whenever possible (and it may not be, I don’t know), I wonder if it would be better to let the underlying map values be TElement | TElement[], promoting to an array only once two entries share a hash. That could make for a lot fewer array allocations for large sets with unique hashes, at the expense of probing the array-likeness of the values, lack of support for TElement itself being array-like, and polymorphism when some entries do share a hash. FWIW I tried this with the ExportInfoMap which is a multimap where you have multiple values when a symbol is re-exported, so in practice that meant that a majority of values were singles but arrays were not uncommon. I couldn’t measure any difference between the always-arrays and arrays-when-needed approaches, so I went with the simpler always-arrays approach like you have here. But I’m curious if you’ve thought about or tried the same thing.

@amcasey
Copy link
Member Author

amcasey commented Mar 11, 2022

@andrewbranch Generally speaking, I'd expect collisions to be pretty common in a hashset, but I have no particular objection to dynamically promoting values to arrays - this is just the simplest code that solved my problem.

Any thoughts on @sandersn's suggestion of clearly separating this from Set<T>?

@andrewbranch
Copy link
Member

andrewbranch commented Mar 11, 2022

Any thoughts on @sandersn's suggestion of clearly separating this from Set<T>?

Personally, I don’t think it’s much of an issue since new Set() ought to be the obvious default to reach for when creating a Set, and the getHashCode and equals parameters are required in your API, so it becomes obvious quickly that you’re not creating a native Set.

@amcasey
Copy link
Member Author

amcasey commented Mar 11, 2022

Re-opening to see if that causes it to pick up the additional commits I pushed.

@amcasey amcasey closed this Mar 11, 2022
@amcasey amcasey reopened this Mar 11, 2022
@amcasey amcasey merged commit ce9657d into microsoft:main Mar 12, 2022
@amcasey amcasey deleted the CustomSet branch March 12, 2022 00:17
@amcasey amcasey mentioned this pull request Apr 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants