-
Notifications
You must be signed in to change notification settings - Fork 13.5k
DO NOT MERGE: Identify places that need reserve. #136543
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
base: main
Are you sure you want to change the base?
DO NOT MERGE: Identify places that need reserve. #136543
Conversation
@kuhar I understand that you are working on improving the performance of I did some experiment with this PR:
One noteworthy point is that I only needed to add a dozen or so calls to I'm wondering if porting those We could detect the presence of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that you are working on improving the performance of llvm::append_range.
I'm interested and attempted to, but I have very few cycles these days (mostly weekends/holidays). The biggest blocker for me is setting up something I can quickly test locally. @nikic provided some instructions but I haven't had time to try that. Ideally, I'd like a large bitcode file I can wget and then a script to run perf for me and give me the numbers back... I've done it before, using gllvm, and have a whole-program .bc for clang, but that bitcode is very old (from 5.0 era?) and probably not useful anymore.
I thought of a similar approach but slightly tweaked -- I left inline comments.
I'm wondering if porting those reserve() calls on SmallPtrSet and such to your patch (#136365) might improve the performance. Also, I am wondering if your patch needs to deal with pointer ranges like char *, which I assume doesn't have an iterator category. Note that ArrayRef uses pointers as iterator types.
Iterator traits/categories should already handle raw pointers -- I don't think there's anything to do here.
The way I'd approach it would be deciding what compile time checks we need:
- has_reserve (which you already have) -- otherwise we can't do much
- has_fast_size (I'd rely on either
llvm::size
or.size()
being present, with the assumption that.size()
is fast) - has_capacity (like you have) -- for debugging/testing only
Then the remaining exercise would be adding .reserve to containers that can benefit from it and potentially removing/renaming .size()
from types where it involves a slow query.
using check_has_member_iterator_category_t = | ||
typename decltype(std::declval<Range &>().begin())::iterator_category; | ||
|
||
template <typename Range> | ||
static constexpr bool HasMemberIteratorCategory = | ||
is_detected<check_has_member_iterator_category_t, Range>::value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iterator_traits should already handle plain pointers, so I think we'd want to use that instead of looking for iterator_category
?
if constexpr (detail::HasMemberCapacity<Container>) | ||
After = C.capacity(); | ||
|
||
if (Before != After) | ||
llvm_unreachable("capacity changed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a cool idea for verifying that it reserved as intended!
if constexpr (detail::HasMemberReserve<Container>) { | ||
using IteratorType = decltype(adl_begin(R)); | ||
if constexpr (std::is_pointer<IteratorType>::value) { | ||
C.reserve(C.size() + std::distance(adl_begin(R), adl_end(R))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alternative would be to check that the type either has .size()
(which we assume to be fast) or that llvm::size
is detected (which already requires random access iterators)
No description provided.