Half or double at the performance lottery

I have been tipped off how to speed up map searches when the key is a string: use transparent comparators.

For a map, it can cut the search time almost in half:

  • use std::less<>
  • use std::string_view

But, surprise: std::unordered_map exhibits a significant loss of search performance when fitted with transparent comparators. Unless I am doing it wrong…

To start, note how the baseline hash performance is much worse than the baseline map one. This goes agains the usual wisdom of hashes being faster than trees for large datasets. The string keys are quite long and the hash time dwarfs both the plain string comparison time and the tree search time.

But the important note is: the transparent comparators are doubling the baseline search time…

Benchmark                          Time             CPU   Iterations items_per_second
-------------------------------------------------------------------------------------
std::map<std::string, x>::find(const std::string&)
BM_plain<std::string>      138476037 ns    138432049 ns            5       14.7943k/s

std::map<std::string, x>::find(cconst char*)
BM_plain<const char*>      141114308 ns    141072829 ns            5       14.5173k/s

std::map<std::string, x, std::less<>>::find(const std::string&)
BM_less<std::string>       140909209 ns    140904323 ns            5       14.5347k/s

std::map<std::string, x>, std::less<>::find(const char*)
BM_less<const char*>        78508113 ns     78502318 ns            8       26.0884k/s

std::map<std::string, x>, std::less<>::find(std::string_view)
BM_less<std::string_view>   77613553 ns     77608860 ns            9       26.3887k/s


std::unordered_map<std::string, x>::find(const std::string&)
BM_Uplain<std::string>      406852133 ns    406840611 ns            2       5.03391k/s

std::unordered_map<std::string, x>::find(cconst char*)
BM_Uplain<const char*>      424539962 ns    424523349 ns            2       4.82423k/s

std::unordered_map<std::string, x, std::equal_to<>>::find(cconst char*)
BM_Uless<const char*>       668691575 ns    668647711 ns            1        3.0629k/s

std::unordered_map<std::string, x, std::equal_to<>>::find(const std::string&)
BM_Uless<std::string>       695774248 ns    695744144 ns            1       2.94361k/s

std::munordered_mapap<std::string, x, std::equal_to<>>, std::less<>::find(std::string_view)
BM_Uless<std::string_view>  631857955 ns    631816680 ns            1       3.24145k/s
Written on June 19, 2024