diff --git a/CMakeLists.txt b/CMakeLists.txt index 21f15d4..fad43d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ if (PHMAP_BUILD_EXAMPLES) add_executable(ex_basic examples/basic.cc phmap.natvis) add_executable(ex_bench examples/bench.cc phmap.natvis) add_executable(ex_emplace examples/emplace.cc phmap.natvis) + add_executable(ex_serialize examples/serialize.cc phmap.natvis) add_executable(ex_hash_std examples/hash_std.cc phmap.natvis) add_executable(ex_hash_value examples/hash_value.cc phmap.natvis) add_executable(ex_two_files examples/f1.cc examples/f2.cc phmap.natvis) diff --git a/examples/serialize.cc b/examples/serialize.cc new file mode 100644 index 0000000..a644672 --- /dev/null +++ b/examples/serialize.cc @@ -0,0 +1,82 @@ +#include +#include +#include +#include "parallel_hashmap/phmap.h" +#include "cereal/types/unordered_map.hpp" +#include "cereal/types/memory.hpp" +#include "cereal/types/bitset.hpp" +#include "cereal/archives/binary.hpp" +#include +#include +#include +#include +#include + +using phmap::flat_hash_map; +using namespace std; +template using milliseconds = std::chrono::duration; + +void showtime(const char *name, std::function doit) +{ + auto t1 = std::chrono::high_resolution_clock::now(); + doit(); + auto t2 = std::chrono::high_resolution_clock::now(); + auto elapsed = milliseconds(t2 - t1).count(); + printf("%s: %.3fms\n", name, (int)elapsed / 1000.0f); +} + +int main() +{ + using MapType = phmap::parallel_flat_hash_map, int>; + MapType table; + const int num_items = 100000000; + + // Iterate and add keys and values + // ------------------------------- + showtime("build hash", [&table, num_items]() { + random_device dev; + mt19937 rng(dev()); + uniform_int_distribution dist6(0,1); + table.reserve(num_items); + for (int i=0; i < num_items; ++i) + { + bitset<42> bs; + for (int j=0; j<42; ++j) + bs[j] = dist6(rng); + table[bs] = i; + } + }); + + // cerealize and save data + // ----------------------- + showtime("serialize", [&table]() { + ofstream os("z:\out.cereal", ios::binary); +#if 0 + const unsigned int length = 8192; + char buffer[length]; + os.rdbuf()->pubsetbuf(buffer, length); +#endif + cereal::BinaryOutputArchive archive(os); + archive(table.size()); + archive(table); + }); + + MapType().swap(table); + + // deserialize + // ----------- + showtime("deserialize", [&table]() { + ifstream is("z:\out.cereal", ios::binary); + cereal::BinaryInputArchive archive_in(is); + size_t table_size; + + archive_in(table_size); + table.reserve(table_size); + archive_in(table); // deserialize from file out.cereal into variable + }); + + + printf("table size: %zu\n", table.size()); + + return 0; +} diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index 8c844ef..748c003 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -1202,6 +1202,8 @@ public: // compared to destruction of the elements of the container. So we pick the // largest bucket_count() threshold for which iteration is still fast and // past that we simply deallocate the array. + if (empty()) + return; if (capacity_ > 127) { destroy_slots(); } else if (capacity_) {