XPath: Optimize insertion_sort

The previous implementation opted for doing two comparisons per element
in the sorted case in order to remove one iterator bounds check per
moved element when we actually need to copy. In our case however the
comparator is pretty expensive (except for remove_duplicates which is
fast as it is) so an extra object comparison hurts much more than an
iterator comparison saves.

This makes sorting by document order up to 3% faster for random
sequences.
This commit is contained in:
Arseny Kapoulkine 2017-02-06 19:25:05 -08:00
parent 8cc3144e7b
commit 774d5fe9df

View File

@ -7216,31 +7216,18 @@ PUGI__NS_BEGIN
return write + 1; return write + 1;
} }
template <typename I> void copy_backwards(I begin, I end, I target) template <typename T, typename Pred> void insertion_sort(T* begin, T* end, const Pred& pred)
{ {
while (begin != end) *--target = *--end; if (begin == end)
} return;
template <typename I, typename Pred, typename T> void insertion_sort(I begin, I end, const Pred& pred, T*) for (T* it = begin + 1; it != end; ++it)
{
assert(begin != end);
for (I it = begin + 1; it != end; ++it)
{ {
T val = *it; T val = *it;
T* hole = it;
if (pred(val, *begin))
{
// move to front
copy_backwards(begin, it, it + 1);
*begin = val;
}
else
{
I hole = it;
// move hole backwards // move hole backwards
while (pred(val, *(hole - 1))) while (hole > begin && pred(val, *(hole - 1)))
{ {
*hole = *(hole - 1); *hole = *(hole - 1);
hole--; hole--;
@ -7250,7 +7237,6 @@ PUGI__NS_BEGIN
*hole = val; *hole = val;
} }
} }
}
// std variant for elements with == // std variant for elements with ==
template <typename I, typename Pred> void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend) template <typename I, typename Pred> void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend)
@ -7359,7 +7345,7 @@ PUGI__NS_BEGIN
} }
// insertion sort small chunk // insertion sort small chunk
if (begin != end) insertion_sort(begin, end, pred, &*begin); insertion_sort(begin, end, pred);
} }
PUGI__NS_END PUGI__NS_END