I changed this code:
auto it = chunks_.begin();
for (;; ++it) {
if (it == chunks_.end()) {
chunks_.emplace_back();
alloc_chunk_ = &chunks_.back();
break;
}
if (!it->is_filled()) {
alloc_chunk_ = &*it;
break;
}
}
to this:
auto it = std::ranges::find_if(
chunks_, [](const auto &chunk) { return !chunk.is_filled(); });
if (it == chunks_.end()) {
chunks_.emplace_back();
alloc_chunk_ = &chunks_.back();
} else {
alloc_chunk_ = &*it;
}
and in both gcc 11.2 -O3, MSVC 19.32 /Ox, the second version was almost 20 times faster. (there was no other code change)
chunks_ is std::vector<Chunk>, and chunks_.size() was approximately 500, and the loop was executed for roughly 100,000 times. The first code was about 500ms, the second code was about 30ms (including all other codes, so clearly this part was the bottleneck)
These are Chunks:
struct Chunk {
// ... other details ...
[[nodiscard]] bool is_filled() const { return !blocks_available_; }
unsigned char data_[num_blocks_];
unsigned char first_available_ = 0;
unsigned char blocks_available_ = num_blocks_;
};
Why the compiler optimizes std::ranges::find_if so fast?