mirror of https://github.com/OpenMW/openmw.git
Use stable sort+unique to collect RefIDs for ESMStore records counting
The idea is to avoid std::map lookup for each CellRef. Instead generate a sequence of added and removed RefNums into a vector then order them by RefNum using a stable sort that preserves relative order of elements with the same RefNum. RefIDs are stored in a different vector to avoid std::string move ctor calls when swapping elements while sorting. Reversed iteration over added and removed RefNums for each unique RefNum is an equivalent to what map-based algorithm produces. The main benefit from sorting a vector is a data locality that means less cache misses for each access. Reduces ESMStore::countRecords perf cycles by 25%.pull/3091/head
parent
9938af2289
commit
1e2aae8095
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef OPENMW_COMPONENTS_MISC_ALGORITHM_H
|
||||||
|
#define OPENMW_COMPONENTS_MISC_ALGORITHM_H
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
template <typename Iterator, typename BinaryPredicate, typename Function>
|
||||||
|
inline Iterator forEachUnique(Iterator begin, Iterator end, BinaryPredicate predicate, Function function)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_base_of_v<
|
||||||
|
std::forward_iterator_tag,
|
||||||
|
typename std::iterator_traits<Iterator>::iterator_category
|
||||||
|
>
|
||||||
|
);
|
||||||
|
if (begin == end)
|
||||||
|
return begin;
|
||||||
|
function(*begin);
|
||||||
|
auto last = begin;
|
||||||
|
++begin;
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
if (!predicate(*begin, *last))
|
||||||
|
{
|
||||||
|
function(*begin);
|
||||||
|
last = begin;
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue