#include #include #include #include #include #include #include #include template using milliseconds = std::chrono::duration; // type containing std::string. Seems to take a long time to construct (and maybe move) // ------------------------------------------------------------------------------------ class custom_type { std::string one = "one"; std::string two = "two"; std::uint32_t three = 3; std::uint64_t four = 4; std::uint64_t five = 5; public: custom_type() = default; // Make object movable and non-copyable custom_type(custom_type &&) = default; custom_type& operator=(custom_type &&) = default; // should be automatically deleted per http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014 //custom_type(custom_type const&) = delete; //custom_type& operator=(custom_type const&) = delete; }; // type containing only integrals. should be faster to create. // ----------------------------------------------------------- class custom_type_2 { std::uint32_t three = 3; std::uint64_t four = 4; std::uint64_t five = 5; std::uint64_t six = 6; public: custom_type_2() = default; // Make object movable and non-copyable custom_type_2(custom_type_2 &&) = default; custom_type_2& operator=(custom_type_2 &&) = default; // should be automatically deleted per http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014 //custom_type_2(custom_type_2 const&) = delete; //custom_type_2& operator=(custom_type_2 const&) = delete; }; // convert std::size_t to appropriate key // -------------------------------------- template struct GenKey { K operator()(std::size_t j); }; template <> struct GenKey { std::string operator()(std::size_t j) { std::ostringstream stm; stm << j; return stm.str(); } }; template <> struct GenKey { int operator()(std::size_t j) { return (int)j; } }; // emplace key + large struct // -------------------------- template struct _emplace { void operator()(Map &m, std::size_t j); }; // "void" template parameter -> use emplace template struct _emplace { void operator()(Map &m, std::size_t j) { m.emplace(GenKey()(j), V()); } }; // "int" template parameter -> use emplace_back for std::vector template struct _emplace { void operator()(Map &m, std::size_t j) { m.emplace_back(GenKey()(j), V()); } }; // The test itself // --------------- template class INSERT> void _test(std::size_t iterations, std::size_t container_size, const char *map_name) { std::size_t count = 0; auto t1 = std::chrono::high_resolution_clock::now(); INSERT insert; for (std::size_t i=0; i(t2 - t1).count(); if (count != iterations*container_size) std::clog << " invalid count: " << count << "\n"; std::clog << map_name << std::fixed << int(elapsed) << " ms\n"; } template class INSERT> void test(std::size_t iterations, std::size_t container_size) { std::clog << "bench: iterations: " << iterations << " / container_size: " << container_size << "\n"; _test, K, V, void, INSERT>(iterations, container_size, " std::map: "); _test, K, V, void, INSERT>(iterations, container_size, " std::unordered_map: "); _test, K, V, void, INSERT>(iterations, container_size, " phmap::flat_hash_map: "); _test>, K, V, int, INSERT> (iterations, container_size, " std::vector: "); std::clog << "\n"; } int main() { std::size_t iterations = 100000; // test with custom_type_2 (int key + 32 byte value). This is representative // of the hash table insertion speed. // ------------------------------------------------------------------------- std::clog << "\n\n" << "testing with " "\n"; std::clog << "---------------------------------" "\n"; test(iterations,10); test(iterations,100); test(iterations,500); // test with custom_type, which contains two std::string values, and use // a generated string key. This is not very indicative of the speed of the // hash itself, as a good chunk of the time is spent creating the keys and // values (as shown by the long times even for std::vector). // ----------------------------------------------------------------------- std::clog << "\n" << "testing with " "\n"; std::clog << "---------------------------------" "\n"; test(iterations,1); test(iterations,10); test(iterations,50); }