-
Notifications
You must be signed in to change notification settings - Fork 168
Add support for amortized resizes #137
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
Conversation
At a high level, I'm a little concerned about the global effect by doing this with a feature. There are trade-offs in this, and that would be okay if a root application crate made this choice (akin to a global allocator), but any crate in the dependency graph could activate this feature affecting |
Yeah, that's a strong point. I guess the flip side is that keeping a separate crate would require ongoing maintenance to keep the projects in sync. I wonder if there's a way for |
Changes here are usually pretty infrequent. The hashbrown change was a biggy, and I do have a few more things lined up, but after that I would expect it to slow down again. Plus, it's not like a fork needs to be aggressive about staying in sync, just good enough for your forked users' needs. I'm not sure what a |
That's true. I guess I'll pursue a fork instead then. Can you give me an idea of the changes you have in mind? As for a |
Direct indexing (#132), and also parameterizing the index type in the raw table (e.g. storing |
Congrats! Not as clever as your previous names though... 😉 |
@cuviper hehe, I figured for this specifically it'd be good to keep the One observation already: the amortize feature vs new crate decision keeps on occurring downstream. For example, I need amortization for |
Keep in mind that since this is a feature, _all_ evmap instances get amortized if _anything_ in the dependency graph enables the feature (indexmap-rs/indexmap#137 (comment)). This is unfortunate, but given that the alternative is forking evmap, we'll go with the feature approach for now. Hopefully one day we'll have a way to [avoid this](rust-lang/cargo#2980 (comment)). Not landing this yet since it's nightly-only at the moment due to certain methods [in `atone`](https://github.com/jonhoo/atone/blob/45ae1e42deaaaaa9a919957ade49982a7ac4655b/src/lib.rs#L58). Nightly-only will go away once rust-lang/rust#70929 and rust-lang/rust#74217 both stabilize. The first one will land on next stable, but the second has some more time to go first.
Keep in mind that since this is a feature, _all_ evmap instances get amortized if _anything_ in the dependency graph enables the feature (indexmap-rs/indexmap#137 (comment)). This is unfortunate, but given that the alternative is forking evmap, we'll go with the feature approach for now. Hopefully one day we'll have a way to [avoid this](rust-lang/cargo#2980 (comment)). Not landing this yet since it's nightly-only at the moment due to certain methods [in `atone`](https://github.com/jonhoo/atone/blob/45ae1e42deaaaaa9a919957ade49982a7ac4655b/src/lib.rs#L58). Nightly-only will go away once rust-lang/rust#70929 and rust-lang/rust#74217 both stabilize. The first one will land on next stable, but the second has some more time to go first.
Hi there!
As you may have seen, over the past few weeks, I've been digging deep down into some latency spikes I was observing when using
IndexMap
. Further investigation revealed that they were caused by resizes, which can get quite expensive as the map grows large. To mitigate the issue, I built an amortized version ofhashbrown
(griddle), and and amortized version ofVec
(atone), and then plugged them intoIndexMap
. This worked really well, and cut my tail latency by several orders of magnitude.I'm opening this mostly to serve as a place to discuss a path forward. It might be that that path forward is to publish a separate crate as I was told to do for
hashbrown
(rust-lang/hashbrown#166 (comment)). I'd be curious to hear your thoughts on including this as a proper feature ofindexmap
.The changes in this PR are actually fairly few, but there were many changes needed just to be able to abstract away the use of
Vec
/slices to something that can be either a slice or anatone::Vc
(this is theEntryVec
type alias). The primary functional changes are:make_contiguous
prior to sorting, which are nightly only (tracking issue)impl Debug for IntoIter
does not print the items withfeature = "amortize"
, sincevec_deque::IntoIter
does not provide by-ref access to the "remainder"capacity
are a little less predictable (see the tests), since the storage is backed by aVecDeque
, not aVec
.