Skip to content
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

Unify the entry and insert code #126

Merged
merged 4 commits into from
Jun 9, 2020
Merged

Conversation

mwillsey
Copy link
Contributor

@mwillsey mwillsey commented Jun 5, 2020

This will close #108

This doesn't so much improve the entry code rather than abstract away entry and insert into a ProbeAction. This forces monomorphization to give us the insert fast path that doesn't require the additional indirection that entry does.

It also implements insert_full on that fast path (insert is now just a call to insert_full), so that should be much faster as well, since it was formerly implemented in terms of entry.

Benchmarks

 name                                   control ns/iter  variable ns/iter  diff ns/iter  diff %  speedup 
 insert_orderedmap_100_000              2,688,143        2,616,739              -71,404  -2.66%   x 1.03 
 insert_orderedmap_10_000               275,198          272,283                 -2,915  -1.06%   x 1.01 
 insert_orderedmap_150                  4,116            3,862                     -254  -6.17%   x 1.07 
 insert_orderedmap_int_bigvalue_10_000  409,681          395,290                -14,391  -3.51%   x 1.04 
 insert_orderedmap_str_10_000           298,722          294,373                 -4,349  -1.46%   x 1.01 
 insert_orderedmap_string_10_000        2,027,784        1,948,038              -79,746  -3.93%   x 1.04 

(index, None)
}
fn steal(self, entry: VacantEntry<'a, K, V>) -> Self::Output {
let index = entry.map.entries.len();
Copy link
Member

@bluss bluss Jun 5, 2020

Choose a reason for hiding this comment

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

this could be just entry.insert_impl::<Sz>(self.0) right? Something like that to reduce duplication - even hit could use that(?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good idea. Do you mean empty could use that? I was afraid that entering the probe loop another time would be costly (technically, you don't have to in the empty case), but it seems to be fine.

Copy link
Contributor Author

@mwillsey mwillsey Jun 5, 2020

Choose a reason for hiding this comment

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

Nvm, turns out doing it in empty isn't great, it basically removes the fast path that the old insert code had, making steal and empty the same.

Copy link
Member

Choose a reason for hiding this comment

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

Are we then maybe identifying the main thing that slows down entry compared with the old insert? Maybe if we updated entry's VacantEntry to skip that loop, for the non-steal case, that insert and entry would match each other in performance?

@bluss
Copy link
Member

bluss commented Jun 5, 2020

That's awesome

src/map.rs Show resolved Hide resolved
src/map.rs Show resolved Hide resolved
src/map.rs Outdated Show resolved Hide resolved
src/map.rs Outdated Show resolved Hide resolved
@bluss
Copy link
Member

bluss commented Jun 5, 2020

Could you update the PR description to use one of the formulations that means that #108 is closed when this is merged? :) https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword

@mwillsey
Copy link
Contributor Author

mwillsey commented Jun 5, 2020

Done!

Copy link
Member

@cuviper cuviper left a comment

Choose a reason for hiding this comment

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

LGTM -- just one typo noted...

src/map.rs Outdated Show resolved Hide resolved
Co-authored-by: Josh Stone <cuviper@gmail.com>
@bluss
Copy link
Member

bluss commented Jun 6, 2020

Thanks. I'll merge this when I have time to make some post-merge edits

@cuviper
Copy link
Member

cuviper commented Jun 9, 2020

@bluss can I help with whatever is blocking this?

@bluss
Copy link
Member

bluss commented Jun 9, 2020

I'll add it as comments. I thought I might as well merge and edit myself, sometimes I prefer that to the back-and-forth, just don't want reviews to be too perfectionist

Copy link
Member

@bluss bluss left a comment

Choose a reason for hiding this comment

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

Thanks a lot for making this PR and improving indexmap. I just put comments on the small things I'd edit if I had time

key: entry.key,
value: self.0,
});
(index, None)
Copy link
Member

Choose a reason for hiding this comment

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

This method body seems "loose" like this - could it not just call a method on the entry? I general, it's hard to follow the insert logic when it's spread out.

(This comment is rather perfectionist, and not something I wanted to make a requirement to fix before merging).

Copy link
Member

Choose a reason for hiding this comment

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

I looked at this -- you'd basically want VacantEntry::insert_impl without the probe loop (since we know its empty). But this needs to consume the entry's key, which makes it harder to reuse that code, so I think we'd end up writing this code separately either way. i.e. It doesn't really matter whether we do it here or there.

(And frankly, a lot of this will disappear if I land the hashbrown changes...)

src/map.rs Show resolved Hide resolved
@cuviper
Copy link
Member

cuviper commented Jun 9, 2020

Yeah, I get that, and sometimes I'll take advantage of maintainer pushes to PRs for that same reason.

I'm pressing because I'm building up changes toward using indexmap more in rustc. 🙂

@cuviper
Copy link
Member

cuviper commented Jun 9, 2020

I fixed the spacing nit, and I think we can wait on the other point.

Thanks @mwillsey!

@cuviper cuviper merged commit 22ecbbb into indexmap-rs:master Jun 9, 2020
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.

Improve .entry() performance
3 participants