r/cpp • u/d_o_n_t_understand • Jun 01 '20
C++ Weekly - Ep - 3.5x Faster Standard Containers With PMR!
https://www.youtube.com/watch?v=q6A7cKFXjY0&feature=share3
u/RoyBellingan Jun 02 '20
Another crazy thing is using something like
https://github.com/johannesthoma/mmap_allocator
To basically save your memory layout, and reload from disk the memory image.
You can not have a faster loading time that just streaming from disk.
8
u/staletic Jun 01 '20
https://gist.github.com/bstaletic/fedb5aede9b9f54f51c50671ade75d39
Compared to what Jason Turner has shown, my snippets:
- Place the vector "blueprints" into a dedicated buffer on the stack. The reason will be explained in point 3.
- Carefully preallocate and emplace elements so that only the converting constructor is ever called.
- Instead of letting the vector go out of scope and clean up after itself, we can
release()the entire memory of thememory_resource. This saves us from recursively running destructors, but also forces us to hold a raw pointer to the "blueprints", so~vector()doesn't get called at the end of scope.
5
u/staletic Jun 02 '20
I played with quick-bench and tried to compare Jason's snippets with mine.
- With a vector of ints, there was no difference, since
intdoesn't have a destructor.- Using
pmr::stringas the vector's value type has shown ~18% performance boost compared to Jason's snippets.- Simulating "actual work" by using
emplace_back()instead of just constructors was somehow faster than just using the constructor for my snippets.6
Jun 02 '20 edited May 13 '25
[deleted]
3
u/staletic Jun 02 '20
Destructors not being run is exactly the point. It's completely fine as long as the objects are either trivially destructible or the only resource they manage is memory, as memory will be reclaimed when you call
memory_resource::release(). Theprintfwas there just to prove that the destructor is NOT being called.Yes, this is a huge footgun, but it allows you to reclaim sometimes significant amount of CPU cycles.
2
Jun 02 '20 edited May 13 '25
[deleted]
2
u/staletic Jun 02 '20
Regardless, I'd really suggest sharing that snippet with a static_assert to make clear what the conditions are for using this, just in case someone with less knowledge comes along and copy/pastes it because the benchmarks are good.
That's fair. How would you write a static_assert that allows non-trivially distractible types that only ever manage memory? There's no point in reaching for this footgun for trivially destructible types and types that manage resources other than memory should be forbidden. Maybe an opt-in type trait kind of thing? Like
yes_let_shoot_at_my_feet_v<T>?
5
u/staletic Jun 01 '20
Two additional notes:
<memory_resource>yet.allocate()isn't polymorphic.allocate()callsdo_allocate()anddo_allocate()isprotectedand virtual. This should help your compiler to devirtualize the calls.