Hi, I've finished integrating the feedback given at the review of boost::container::hub: * Branch: https://github.com/joaquintides/hub/tree/feature/review-feedback * PR: https://github.com/joaquintides/hub/pull/20 * Changes: * Fix typos (Matt Borland) * Fix test_api for GCC on darwin (Matt Borland) * Fix iterator de-reference (Matt Borland) * enabled warnings in CI (Matt Borland) * removed undocumented memory() (Andrzej Krzemieński) * typos (Arnaud Becheler) * worked around bogus array bounds warning in GCC (Andrzej Krzemieński/Peter Dimov) * integrated AppVeyor CI (Alexander Grund) * hardened get_iterator (Emil Dotchevski) * Fix B2 + CMake testing (Matt Borland) * replaced visit[_all][_while] with global for_each[_while] (Andrzej Krzemieński) * used aligned new when available and required (Emil Dotchevski) * added exception safety tests and made single-element insertion strongly safe (Emil Dotchevski) * clarified exception guarantees and preconditions of sort (Emil Dotchevski) * s/HFT/high-frequency trading (Peter Turcan) * improved somewhat introductory statement to hub (Peter Turcan, Arnaud Becheler) * made it clear that hub is not a sequence container (Andrzej Krzemieński) * reserved right to change block capacity (64 elements) in the future (Emil Dotchevski) * explained by block size is 64 (Peter Turcan) * improve code comments in tutorial, expanded section on capacity (Peter Turcan, Arnaud Becheler) Review feedback _not_ included in this version: * Implement a slot map (Chris Mazakas): this is more for the evolution track * Contiguous hub with VirtualAlloc (Chris Mazakas): same * Improve perf table presentation (Matt Borland/Dominique Devienne): I'll see to that when the docs are integrated into Boost.Container's I'd be grateful if you could take a look, comment and maybe warn about feedback I may have overlooked. When Ion gives me the OK, I'll merge and begin working with him on integration into Boost.Container, hopefully in time for Boost 1.92. Thank you, Joaquín M López Muñoz
Hi ! I found the documentation incredibly better. Those figures are rocking :D And the benchmarks remain impressive. Best, Arnaud
i think i agree, even though i am not sure if i really know what you mean Sent: Monday, May 25, 2026 at 2:09 AM From: "Arnaud Becheler via Boost" <boost@lists.boost.org> To: "Boost developers' mailing list" <boost@lists.boost.org> Cc: "Joaquin M López Muñoz" <joaquin.lopezmunoz@gmail.com>, "Ion Gaztañaga" <igaztanaga@gmail.com>, "Arnaud Becheler" <arnaud.becheler@gmail.com> Subject: [boost] Re: [hub] Post-review version ready Hi ! I found the documentation incredibly better. Those figures are rocking :D And the benchmarks remain impressive. Best, Arnaud _______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org [1]https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: [2]https://lists.boost.org/archives/list/boost@lists.boost.org/message/ 7OWLGIFCB7YROZQM5ZFBDOIYH7W43BSA/ References 1. https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ 2. https://lists.boost.org/archives/list/boost@lists.boost.org/message/7OWLGIFC...
Hey Joaquin, thanks for our personal discussion on this stuff, I think we've both improved our respective containers. Just to chime in in a more official capacity, good to see you've provided some post-iteration erasure results, I think that balances things out a bit, though it still lacks some longitudinal churn testing. If you want, you're welcome to link to my benchmarking in your docs. I realised visitation-like prefetching can be applied as a hive overload of std::for_each, hopefully will have time to do that at some point, and will be interesting to see the difference. Also glad to see the plf:: stuff is separate from the std:: stuff. / Minor corrections to the docs:/ "|boost::container::hub| does not conform to the specification of |std::hive| in a few aspects: * Minimum and maximum block size limits can't be specified and are fixed (to 64 in this implementation). |reshape| is not provided as it doesn't make sense when block capacity is fixed." That wording (inadvertently) suggests that min/max can't be fixed and equal in a std::hive implementation, which isn't the case. Better phrasing: |boost::container::hub| does not conform to the specification of |std::hive| in a few aspects: * Minimum and maximum block capacity limits can't be specified and are fixed to (to 64 in this implementation). The std::hive spec allows for this, but due to this we've decided to not provide reshape() or constructors which take capacity-limit arguments, since these would not result in any effect on the instance's capacity limits. In addition block_capacity_limits(), block_capacity_default_limits() and block_capacity_hard_limits() are not provided as they would always return 64, 64. Likewise the following is slightly ambiguous: "The |end| iterator is stable and non-transferable, whereas for |std::hive| the |end| iterator is invalidated upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| behaves like |std::vector::end|). Technically, this is not a non-conformance but rather an extension to the specification of |std::hive|." I would word it like this: "The |end| iterator is guaranteed to be stable and non-transferable, whereas for |std::hive| the |end| iterator is allowed to invalidate upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| is allowed to behave like either |std::list::end| or std::vector::end)." Though less important, I would change the bit about three-way-comparable from 'overhead' to 'overhead for small elements', since for a 6-word type, an additional 1 word per (6x64) 384-word block makes no measurable difference to cache locality , though it does when dealing with 8->64-bit types. re: Bookkeeping, in my hive benchmarking with/without the group number metadata it made no difference except for splicing, since otherwise the numbers are in pragmatic reality pretty much never updated. Also, if you intend to fix that behaviour we talked about regarding iteration/visitation performance degradation over time (due to blocks which become empty not being moved to the tail of the 'available' list, and non-empty blocks thereby not being preferentially-used during insertion, resulting in greater gaps during iteration) you can remove the line "trim_capacity is linear on the number of available blocks (std::hive::trim_capacity is linear on the number of reserved blocks, i.e. those without any used slot).". As, once that aspect is fixed that it becomes possible to implement trim_capacity() as linear in the number of reserved blocks, by iterating backwards from the tail and stopping once a block with active elements is found. Finally a note re: Andrezj's container category note, this is a hive-lite container, therefore a sequence container, according to the standard: "organizes a finite set of objects, all of the same type, into a strictly linear arrangement". "In addition, array and hive are provided as sequence containers which provide limited sequence operations, in array's case because it has a fixed number of elements, and in hive's case because insertion order is unspecified.". "Limited" in the case of hive means no insertion position in insert/emplace functions. Otherwise there are no pragmatic differences. Cheers once again- Matt On 24/05/2026 5:36 am, Joaquin M López Muñoz via Boost wrote:
Hi,
I've finished integrating the feedback given at the review of boost::container::hub:
* Branch: https://github.com/joaquintides/hub/tree/feature/review-feedback * PR: https://github.com/joaquintides/hub/pull/20 * Changes: * Fix typos (Matt Borland) * Fix test_api for GCC on darwin (Matt Borland) * Fix iterator de-reference (Matt Borland) * enabled warnings in CI (Matt Borland) * removed undocumented memory() (Andrzej Krzemieński) * typos (Arnaud Becheler) * worked around bogus array bounds warning in GCC (Andrzej Krzemieński/Peter Dimov) * integrated AppVeyor CI (Alexander Grund) * hardened get_iterator (Emil Dotchevski) * Fix B2 + CMake testing (Matt Borland) * replaced visit[_all][_while] with global for_each[_while] (Andrzej Krzemieński) * used aligned new when available and required (Emil Dotchevski) * added exception safety tests and made single-element insertion strongly safe (Emil Dotchevski) * clarified exception guarantees and preconditions of sort (Emil Dotchevski) * s/HFT/high-frequency trading (Peter Turcan) * improved somewhat introductory statement to hub (Peter Turcan, Arnaud Becheler) * made it clear that hub is not a sequence container (Andrzej Krzemieński) * reserved right to change block capacity (64 elements) in the future (Emil Dotchevski) * explained by block size is 64 (Peter Turcan) * improve code comments in tutorial, expanded section on capacity (Peter Turcan, Arnaud Becheler)
Review feedback _not_ included in this version:
* Implement a slot map (Chris Mazakas): this is more for the evolution track * Contiguous hub with VirtualAlloc (Chris Mazakas): same * Improve perf table presentation (Matt Borland/Dominique Devienne): I'll see to that when the docs are integrated into Boost.Container's
I'd be grateful if you could take a look, comment and maybe warn about feedback I may have overlooked. When Ion gives me the OK, I'll merge and begin working with him on integration into Boost.Container, hopefully in time for Boost 1.92.
Thank you,
Joaquín M López Muñoz
_______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/5CZTSS3C...
Ugh, I meant "post-erasure iteration results" :| On 27/05/2026 12:29 pm, Matt Bentley wrote:
Hey Joaquin,
thanks for our personal discussion on this stuff, I think we've both improved our respective containers.
Just to chime in in a more official capacity, good to see you've provided some post-iteration erasure results, I think that balances things out a bit, though it still lacks some longitudinal churn testing. If you want, you're welcome to link to my benchmarking in your docs. I realised visitation-like prefetching can be applied as a hive overload of std::for_each, hopefully will have time to do that at some point, and will be interesting to see the difference.
Also glad to see the plf:: stuff is separate from the std:: stuff.
/ Minor corrections to the docs:/
"|boost::container::hub| does not conform to the specification of |std::hive| in a few aspects:
* Minimum and maximum block size limits can't be specified and are fixed (to 64 in this implementation). |reshape| is not provided as it doesn't make sense when block capacity is fixed."
That wording (inadvertently) suggests that min/max can't be fixed and equal in a std::hive implementation, which isn't the case. Better phrasing:
|boost::container::hub| does not conform to the specification of |std::hive| in a few aspects:
* Minimum and maximum block capacity limits can't be specified and are fixed to (to 64 in this implementation). The std::hive spec allows for this, but due to this we've decided to not provide reshape() or constructors which take capacity-limit arguments, since these would not result in any effect on the instance's capacity limits. In addition block_capacity_limits(), block_capacity_default_limits() and block_capacity_hard_limits() are not provided as they would always return 64, 64.
Likewise the following is slightly ambiguous:
"The |end| iterator is stable and non-transferable, whereas for |std::hive| the |end| iterator is invalidated upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| behaves like |std::vector::end|). Technically, this is not a non-conformance but rather an extension to the specification of |std::hive|."
I would word it like this:
"The |end| iterator is guaranteed to be stable and non-transferable, whereas for |std::hive| the |end| iterator is allowed to invalidate upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| is allowed to behave like either |std::list::end| or std::vector::end)."
Though less important, I would change the bit about three-way-comparable from 'overhead' to 'overhead for small elements', since for a 6-word type, an additional 1 word per (6x64) 384-word block makes no measurable difference to cache locality , though it does when dealing with 8->64-bit types. re: Bookkeeping, in my hive benchmarking with/without the group number metadata it made no difference except for splicing, since otherwise the numbers are in pragmatic reality pretty much never updated.
Also, if you intend to fix that behaviour we talked about regarding iteration/visitation performance degradation over time (due to blocks which become empty not being moved to the tail of the 'available' list, and non-empty blocks thereby not being preferentially-used during insertion, resulting in greater gaps during iteration) you can remove the line "trim_capacity is linear on the number of available blocks (std::hive::trim_capacity is linear on the number of reserved blocks, i.e. those without any used slot).". As, once that aspect is fixed that it becomes possible to implement trim_capacity() as linear in the number of reserved blocks, by iterating backwards from the tail and stopping once a block with active elements is found.
Finally a note re: Andrezj's container category note, this is a hive-lite container, therefore a sequence container, according to the standard: "organizes a finite set of objects, all of the same type, into a strictly linear arrangement". "In addition, array and hive are provided as sequence containers which provide limited sequence operations, in array's case because it has a fixed number of elements, and in hive's case because insertion order is unspecified.". "Limited" in the case of hive means no insertion position in insert/emplace functions. Otherwise there are no pragmatic differences.
Cheers once again-
Matt
On 24/05/2026 5:36 am, Joaquin M López Muñoz via Boost wrote:
Hi,
I've finished integrating the feedback given at the review of boost::container::hub:
* Branch: https://github.com/joaquintides/hub/tree/feature/review-feedback * PR: https://github.com/joaquintides/hub/pull/20 * Changes: * Fix typos (Matt Borland) * Fix test_api for GCC on darwin (Matt Borland) * Fix iterator de-reference (Matt Borland) * enabled warnings in CI (Matt Borland) * removed undocumented memory() (Andrzej Krzemieński) * typos (Arnaud Becheler) * worked around bogus array bounds warning in GCC (Andrzej Krzemieński/Peter Dimov) * integrated AppVeyor CI (Alexander Grund) * hardened get_iterator (Emil Dotchevski) * Fix B2 + CMake testing (Matt Borland) * replaced visit[_all][_while] with global for_each[_while] (Andrzej Krzemieński) * used aligned new when available and required (Emil Dotchevski) * added exception safety tests and made single-element insertion strongly safe (Emil Dotchevski) * clarified exception guarantees and preconditions of sort (Emil Dotchevski) * s/HFT/high-frequency trading (Peter Turcan) * improved somewhat introductory statement to hub (Peter Turcan, Arnaud Becheler) * made it clear that hub is not a sequence container (Andrzej Krzemieński) * reserved right to change block capacity (64 elements) in the future (Emil Dotchevski) * explained by block size is 64 (Peter Turcan) * improve code comments in tutorial, expanded section on capacity (Peter Turcan, Arnaud Becheler)
Review feedback _not_ included in this version:
* Implement a slot map (Chris Mazakas): this is more for the evolution track * Contiguous hub with VirtualAlloc (Chris Mazakas): same * Improve perf table presentation (Matt Borland/Dominique Devienne): I'll see to that when the docs are integrated into Boost.Container's
I'd be grateful if you could take a look, comment and maybe warn about feedback I may have overlooked. When Ion gives me the OK, I'll merge and begin working with him on integration into Boost.Container, hopefully in time for Boost 1.92.
Thank you,
Joaquín M López Muñoz
_______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/5CZTSS3C...
El 27/05/2026 a las 2:29, Matt Bentley escribió:
Hey Joaquin,
thanks for our personal discussion on this stuff, I think we've both improved our respective containers.
Thank _you_, it's been a most instructive exchange.
Just to chime in in a more official capacity, good to see you've provided some post-iteration erasure results, I think that balances things out a bit, though it still lacks some longitudinal churn testing.
? Post-erase iteration benchmarks were there all along. Maybe the confusion arises because what used to be called "for_each" and "visit all" is now called "range for" and "for_each" respectively, after the syntax change proposed by Andrzej (namely, replacing visit[_while] member functions with global std::algorithm-like for_each[_while] functions).
If you want, you're welcome to link to my benchmarking in your docs. I realised visitation-like prefetching can be applied as a hive overload of std::for_each, hopefully will have time to do that at some point, and will be interesting to see the difference.
Also glad to see the plf:: stuff is separate from the std:: stuff.
/ Minor corrections to the docs:/
"|boost::container::hub| does not conform to the specification of |std::hive| in a few aspects:
* Minimum and maximum block size limits can't be specified and are fixed (to 64 in this implementation). |reshape| is not provided as it doesn't make sense when block capacity is fixed."
That wording (inadvertently) suggests that min/max can't be fixed and equal in a std::hive implementation, which isn't the case. Better phrasing:
|boost::container::hub| does not conform to the specification of |std::hive| in a few aspects:
* Minimum and maximum block capacity limits can't be specified and are fixed to (to 64 in this implementation). The std::hive spec allows for this, but due to this we've decided to not provide reshape() or constructors which take capacity-limit arguments, since these would not result in any effect on the instance's capacity limits. In addition block_capacity_limits(), block_capacity_default_limits() and block_capacity_hard_limits() are not provided as they would always return 64, 64.
Yes, I can rewrite that part. As you have pointed out here and elsewhere, the non-conformance is, strictly speaking, not a technical one, as boost::container::hub could always provide a dummy hive_limits interface.
Likewise the following is slightly ambiguous:
"The |end| iterator is stable and non-transferable, whereas for |std::hive| the |end| iterator is invalidated upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| behaves like |std::vector::end|). Technically, this is not a non-conformance but rather an extension to the specification of |std::hive|."
I would word it like this:
"The |end| iterator is guaranteed to be stable and non-transferable, whereas for |std::hive| the |end| iterator is allowed to invalidate upon any insertion or the erasure of the last element (briefly put, |boost::container::hub::end| behaves like |std::list::end| whereas |std::hive::end| is allowed to behave like either |std::list::end| or std::vector::end)."
Will use this, thank you.
Though less important, I would change the bit about three-way-comparable from 'overhead' to 'overhead for small elements', since for a 6-word type, an additional 1 word per (6x64) 384-word block makes no measurable difference to cache locality , though it does when dealing with 8->64-bit types. re: Bookkeeping, in my hive benchmarking with/without the group number metadata it made no difference except for splicing, since otherwise the numbers are in pragmatic reality pretty much never updated.
Noted.
Also, if you intend to fix that behaviour we talked about regarding iteration/visitation performance degradation over time (due to blocks which become empty not being moved to the tail of the 'available' list, and non-empty blocks thereby not being preferentially-used during insertion, resulting in greater gaps during iteration) you can remove the line "trim_capacity is linear on the number of available blocks (std::hive::trim_capacity is linear on the number of reserved blocks, i.e. those without any used slot).". As, once that aspect is fixed that it becomes possible to implement trim_capacity() as linear in the number of reserved blocks, by iterating backwards from the tail and stopping once a block with active elements is found.
After our talk I went and did exactly as you suggested: https://github.com/joaquintides/hub/compare/feature/review-feedback...featur... I'm measuring performance right now but seems like this is not producing any real degradation, so it'll go in. This also removes one of the non-conformances of boost::container::hub wrt to std::hive spec.
Finally a note re: Andrezj's container category note, this is a hive-lite container, therefore a sequence container, according to the standard: "organizes a finite set of objects, all of the same type, into a strictly linear arrangement". "In addition, array and hive are provided as sequence containers which provide limited sequence operations, in array's case because it has a fixed number of elements, and in hive's case because insertion order is unspecified.". "Limited" in the case of hive means no insertion position in insert/emplace functions. Otherwise there are no pragmatic differences.
This stemmed from an objection by Andrzej. Originally hub was presented as a sequence container, much in line with the standard text for std::hive, but I then leaned towards Andrzej's stance that this is misleading because the core functionality that makes a container a sequence, namely control of positioning, is not provided. I guess the committee does not have the appetite (understandably so) for making great rearrangements of the text, but IMHO this would have called for a new kind of "unordered containers". Anyway, the current writing is a bit in between, it doesn't call the container a sequence container right away but then in the reference it states (https://github.com/joaquintides/hub/tree/feature/review-feedback#class-templ...): /boost::container::hub<T, Allocator> is also a model of SequenceContainer, with the following exception: * Positional insertion operations of the form insert(position, ...) or emplace(position, ...) are not provided or ignore the position argument. / I readily admit this is all quite non-committal to either side of the discussion :-)
Cheers once again-
Matt
Thanks for your feedback, Joaquín M López Muñoz
On Wed, 27 May 2026 at 21:37, Joaquin M López Muñoz < joaquin.lopezmunoz@gmail.com> wrote:
El 27/05/2026 a las 2:29, Matt Bentley escribió:
Hey Joaquin,
thanks for our personal discussion on this stuff, I think we've both improved our respective containers.
Thank _you_, it's been a most instructive exchange.
Just to chime in in a more official capacity, good to see you've provided some post-iteration erasure results, I think that balances things out a bit, though it still lacks some longitudinal churn testing.
? Post-erase iteration benchmarks were there all along. Maybe the confusion arises because what used to be called "for_each" and "visit all" is now called "range for" and "for_each" respectively, after the syntax change proposed by Andrzej (namely, replacing visit[_while] member functions with global std::algorithm-like for_each[_while] functions).
Ah, I see.
boost::container::hub does not conform to the specification of std::hive in a few aspects:
- Minimum and maximum block capacity limits can't be specified and are fixed to (to 64 in this implementation). The std::hive spec allows for this, but due to this we've decided to not provide reshape() or constructors which take capacity-limit arguments, since these would not result in any effect on the instance's capacity limits. In addition block_capacity_limits(), block_capacity_default_limits() and block_capacity_hard_limits() are not provided as they would always return 64, 64.
Yes, I can rewrite that part. As you have pointed out here and elsewhere, the non-conformance is, strictly speaking, not a technical one, as boost::container::hub could always provide a dummy hive_limits interface.
Probably a good idea, if you want people to be able to swap in/out the different container styles.
Also, if you intend to fix that behaviour we talked about regarding iteration/visitation performance degradation over time (due to blocks which become empty not being moved to the tail of the 'available' list, and non-empty blocks thereby not being preferentially-used during insertion, resulting in greater gaps during iteration) you can remove the line "trim_capacity is linear on the number of available blocks (std::hive::trim_capacity is linear on the number of reserved blocks, i.e. those without any used slot).". As, once that aspect is fixed that it becomes possible to implement trim_capacity() as linear in the number of reserved blocks, by iterating backwards from the tail and stopping once a block with active elements is found.
After our talk I went and did exactly as you suggested:
https://github.com/joaquintides/hub/compare/feature/review-feedback...featur...
I'm measuring performance right now but seems like this is not producing any real degradation, so it'll go in. This also removes one of the non-conformances of boost::container::hub wrt to std::hive spec.
Sounds good - I'll check to see if there's any performance change in the longitudinal tests afterward, if I get time. I'll add a note re: forced inlining. In the past I enabled this for some things like operator++, but found it pessimised. The compiler seems to be much better at this that we are. However, you'd need to measure before-and-after stats for your own case - not against my container (as forced inlining will definitely preferentially inline some of your code), but against your own pre-removal readings. Removing my container from that benchmark would probably help to get accurate results in this particular case.
Finally a note re: Andrezj's container category note, this is a hive-lite container, therefore a sequence container, according to the standard: "organizes a finite set of objects, all of the same type, into a strictly linear arrangement". "In addition, array and hive are provided as sequence containers which provide limited sequence operations, in array's case because it has a fixed number of elements, and in hive's case because insertion order is unspecified.". "Limited" in the case of hive means no insertion position in insert/emplace functions. Otherwise there are no pragmatic differences.
This stemmed from an objection by Andrzej. Originally hub was presented as a sequence container, much in line with the standard text for std::hive, but I then leaned towards Andrzej's stance that this is misleading because the core functionality that makes a container a sequence, namely control of positioning, is not provided. I guess the committee does not have the appetite (understandably so) for making great rearrangements of the text, but IMHO this would have called for a new kind of "unordered containers". Anyway, the current writing is a bit in between, it doesn't call the container a sequence container right away but then in the reference it states ( https://github.com/joaquintides/hub/tree/feature/review-feedback#class-templ... ):
*boost::container::hub<T, Allocator> is also a model of SequenceContainer, with the following exception: * Positional insertion operations of the form insert(position, ...) or emplace(position, ...) are not provided or ignore the position argument.*
Yes, they're mostly grouping categories, rather than technical categories, since technically std::map also presents elements in a linear sequence if you iterate, but regardless of any hair-splitting I think your wording is good! Cheers, M@
El 28/05/2026 a las 3:16, Matthew Bentley escribió:
[...] I'll add a note re: forced inlining. In the past I enabled this for some things like operator++, but found it pessimised. The compiler seems to be much better at this that we are. However, you'd need to measure before-and-after stats for your own case - not against my container (as forced inlining will definitely preferentially inline some of your code), but against your own pre-removal readings. Removing my container from that benchmark would probably help to get accurate results in this particular case.
I've checked locally in the past with and without forced inlining: GCC and Clang do not seem to be really affected, but MSVC benefits a bit. We observed a similar behavior when working with boost::unordered_flat_map, my impression is that MSVC has a very low inlining budget. I may revisit this again anyway, never hurts to double check. Thank you, Joaquín M López Muñoz
On 29/05/2026 6:35 am, Joaquin M López Muñoz wrote:
El 28/05/2026 a las 3:16, Matthew Bentley escribió:
[...] I'll add a note re: forced inlining. In the past I enabled this for some things like operator++, but found it pessimised. The compiler seems to be much better at this that we are. However, you'd need to measure before-and-after stats for your own case - not against my container (as forced inlining will definitely preferentially inline some of your code), but against your own pre-removal readings. Removing my container from that benchmark would probably help to get accurate results in this particular case.
I've checked locally in the past with and without forced inlining: GCC and Clang do not seem to be really affected, but MSVC benefits a bit. We observed a similar behavior when working with boost::unordered_flat_map, my impression is that MSVC has a very low inlining budget. I may revisit this again anyway, never hurts to double check.
Thank you,
Joaquín M López Muñoz
Yes and to be fair it was a long time ago when I checked this, and compilers change their policies all the time :/ You might want to look at my overloads for distance/advance - they all follow the same pattern as range-erase (between O(1) and O(n), typically O(log n)). You'd have to use ADL of course. Cheers, M
El 29/05/2026 a las 2:02, Matt Bentley escribió:
On 29/05/2026 6:35 am, Joaquin M López Muñoz wrote:
El 28/05/2026 a las 3:16, Matthew Bentley escribió:
[...] I'll add a note re: forced inlining. In the past I enabled this for some things like operator++, but found it pessimised. The compiler seems to be much better at this that we are. However, you'd need to measure before-and-after stats for your own case - not against my container (as forced inlining will definitely preferentially inline some of your code), but against your own pre-removal readings. Removing my container from that benchmark would probably help to get accurate results in this particular case.
I've checked locally in the past with and without forced inlining: GCC and Clang do not seem to be really affected, but MSVC benefits a bit. We observed a similar behavior when working with boost::unordered_flat_map, my impression is that MSVC has a very low inlining budget. I may revisit this again anyway, never hurts to double check.
Thank you,
Joaquín M López Muñoz
Yes and to be fair it was a long time ago when I checked this, and compilers change their policies all the time :/
You might want to look at my overloads for distance/advance - they all follow the same pattern as range-erase (between O(1) and O(n), typically O(log n)). You'd have to use ADL of course.
Yes, hub could do something similar. The bad thing about _not_ being a container in the stdlib is that you must rely on the user doing ADL for it, as you mention. On a somewhat related note, Ion has been experimenting with efficient algorithms for segmented iterators: https://boostedcpp.net/2026/05/18/neoclassical-c-segmented-iterators-revisit... Some stdlib implementations like libc++ use these techniques _internally_, which negates the potential benefits to external libraries. It'd be terrific if Ion could eventually work out a std proposal for this, but I don't know if this is his appetite. Joaquín M López Muñoz
participants (6)
-
Arnaud Becheler -
Ion Gaztañaga -
Joaquin M López Muñoz -
Matt Bentley -
Matthew Bentley -
Peter Taraba