AK: Make Vector::remove_all_matching O(n) instead of O(n²)
If multiple entries match during a single run of Vector::remove_all_matching(), the contents of the vector would shift back multiple times as well. This provides a new approach that iterates only once over each entry. Improves the provided benchmark case (running 1000 iterations) from ~900ms to ~8ms on my machine.
This commit is contained in:
parent
4c58be255a
commit
68035fbd98
2 changed files with 27 additions and 8 deletions
25
AK/Vector.h
25
AK/Vector.h
|
|
@ -590,16 +590,25 @@ public:
|
|||
template<typename TUnaryPredicate>
|
||||
bool remove_all_matching(TUnaryPredicate const& predicate)
|
||||
{
|
||||
bool something_was_removed = false;
|
||||
for (size_t i = 0; i < size();) {
|
||||
if (predicate(at(i))) {
|
||||
remove(i);
|
||||
something_was_removed = true;
|
||||
} else {
|
||||
++i;
|
||||
size_t write_index = 0;
|
||||
for (size_t read_index = 0; read_index < m_size; ++read_index) {
|
||||
if (predicate(at(read_index))) {
|
||||
TypedTransfer<StorageType>::delete_(slot(read_index), 1);
|
||||
continue;
|
||||
}
|
||||
if (read_index != write_index) {
|
||||
TypedTransfer<StorageType>::move(slot(write_index), slot(read_index), 1);
|
||||
TypedTransfer<StorageType>::delete_(slot(read_index), 1);
|
||||
}
|
||||
++write_index;
|
||||
}
|
||||
return something_was_removed;
|
||||
|
||||
if (write_index == m_size)
|
||||
return false;
|
||||
|
||||
m_size = write_index;
|
||||
update_metadata();
|
||||
return true;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T take_last()
|
||||
|
|
|
|||
|
|
@ -247,6 +247,16 @@ static bool is_inline_element(auto& el, auto& vector)
|
|||
EXPECT_EQ(ints.size(), 0u); \
|
||||
} \
|
||||
\
|
||||
BENCHMARK_CASE(Vector##_remove_all_matching_trivial) \
|
||||
{ \
|
||||
Vector<int> ints; \
|
||||
for (int i = 0; i < 10000; ++i) { \
|
||||
ints.append(i); \
|
||||
} \
|
||||
ints.remove_all_matching([](int value) { return value % 2 == 0; }); \
|
||||
EXPECT_EQ(ints.size(), 5000u); \
|
||||
} \
|
||||
\
|
||||
TEST_CASE(Vector##_vector_remove) \
|
||||
{ \
|
||||
Vector<int> ints; \
|
||||
|
|
|
|||
Loading…
Reference in a new issue