O P T I O N S
This commit is contained in:
62
src/clang-format
Normal file
62
src/clang-format
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
BasedOnStyle: WebKit
|
||||
AccessModifierOffset: '0'
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: 'true'
|
||||
AlignConsecutiveAssignments: 'true'
|
||||
AlignEscapedNewlines: Left
|
||||
AlignTrailingComments: 'true'
|
||||
AllowAllArgumentsOnNextLine: 'true'
|
||||
AllowAllConstructorInitializersOnNextLine: 'true'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'true'
|
||||
AllowShortBlocksOnASingleLine: 'true'
|
||||
AllowShortCaseLabelsOnASingleLine: 'true'
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AlwaysBreakTemplateDeclarations: 'Yes'
|
||||
BinPackArguments: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Stroustrup
|
||||
BreakBeforeTernaryOperators: 'false'
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakInheritanceList: AfterColon
|
||||
BreakStringLiterals: 'true'
|
||||
ColumnLimit: '100'
|
||||
CompactNamespaces: 'true'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
ConstructorInitializerIndentWidth: '4'
|
||||
ContinuationIndentWidth: '4'
|
||||
Cpp11BracedListStyle: 'true'
|
||||
DerivePointerAlignment: 'false'
|
||||
DisableFormat: 'false'
|
||||
FixNamespaceComments: 'true'
|
||||
IncludeBlocks: Merge
|
||||
IndentCaseLabels: 'true'
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'false'
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'true'
|
||||
Language: Cpp
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
ReflowComments: 'true'
|
||||
SortIncludes: 'true'
|
||||
SortUsingDeclarations: 'true'
|
||||
SpaceAfterCStyleCast: 'true'
|
||||
SpaceAfterLogicalNot: 'false'
|
||||
SpaceAfterTemplateKeyword: 'false'
|
||||
SpaceBeforeAssignmentOperators: 'true'
|
||||
SpaceBeforeCpp11BracedList: 'true'
|
||||
SpaceBeforeCtorInitializerColon: 'false'
|
||||
SpaceBeforeInheritanceColon: 'false'
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: 'true'
|
||||
SpacesInAngles: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInContainerLiterals: 'false'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Cpp11
|
||||
UseTab: ForContinuationAndIndentation
|
||||
|
||||
...
|
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "./includes/generator.h"
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ std::string gen_unsuccesfull_string() { // 90^size posibilities
|
||||
return randomstring;
|
||||
}
|
||||
|
||||
int gen_int(){
|
||||
int gen_int() {
|
||||
return insert_int(generator);
|
||||
}
|
||||
|
||||
int gen_unsuccesfull_int(){
|
||||
int gen_unsuccesfull_int() {
|
||||
return noninsert_int(generator);
|
||||
}
|
||||
|
8223
src/includes/3thparty/CLI11.hpp
Normal file
8223
src/includes/3thparty/CLI11.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,16 +5,15 @@
|
||||
#include "./tests.h"
|
||||
|
||||
vector<int> sizes = {
|
||||
50000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000,
|
||||
600000, 700000, 800000, 900000, 1000000,
|
||||
// 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000, 10000000,
|
||||
// 15000000, 20000000, 25000000, 30000000, 35000000, 40000000, 45000000, 50000000
|
||||
50000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 500000,
|
||||
600000, 700000, 800000, 900000, 1000000,
|
||||
// 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000, 10000000,
|
||||
// 15000000, 20000000, 25000000, 30000000, 35000000, 40000000, 45000000, 50000000
|
||||
};
|
||||
// to print type info
|
||||
|
||||
template <typename T>
|
||||
constexpr auto type_name()
|
||||
{
|
||||
template<typename T>
|
||||
constexpr auto type_name() {
|
||||
std::string_view name, prefix, suffix;
|
||||
#ifdef __clang__
|
||||
name = __PRETTY_FUNCTION__;
|
||||
@@ -32,73 +31,70 @@ constexpr auto type_name()
|
||||
name.remove_prefix(prefix.size());
|
||||
name.remove_suffix(suffix.size());
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
std::basic_string_view<char> name(T var){
|
||||
std::basic_string_view<char> name(T var) {
|
||||
return type_name<decltype(var)>();
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void int_test_aggregate(T map, int runs){
|
||||
void int_test_aggregate(T map, int runs) {
|
||||
std::ofstream output{"results.csv", std::ios_base::app};
|
||||
for (int i = 0; i < runs; ++i){
|
||||
for (int i = 0; i < runs; ++i) {
|
||||
string insert = "\nint_insert, '";
|
||||
string succ_lookup = "\nint_succ_lookup, '";
|
||||
string nosucc_lookup = "\nint_nosucc_lookup, '";
|
||||
string delet = "\nint_delete, '";
|
||||
|
||||
insert += string{name(map)} + "'";
|
||||
succ_lookup += string{name(map)} + "'" ;
|
||||
nosucc_lookup += string{name(map)} +"'" ;
|
||||
delet += string{name(map)} + "'" ;
|
||||
for ( auto size : sizes){
|
||||
insert += string{name(map)} + "'";
|
||||
succ_lookup += string{name(map)} + "'";
|
||||
nosucc_lookup += string{name(map)} + "'";
|
||||
delet += string{name(map)} + "'";
|
||||
for (auto size : sizes) {
|
||||
vector<int> results = int_test(map, size);
|
||||
|
||||
|
||||
insert += ", " + std::to_string(results[0]);
|
||||
succ_lookup += ", " + std::to_string(results[1]);
|
||||
nosucc_lookup +=", " + std::to_string(results[2]);
|
||||
nosucc_lookup += ", " + std::to_string(results[2]);
|
||||
delet += ", " + std::to_string(results[3]);
|
||||
}
|
||||
output << insert << succ_lookup << nosucc_lookup << delet;
|
||||
cout << insert << succ_lookup << nosucc_lookup << delet;
|
||||
|
||||
output << insert << succ_lookup << nosucc_lookup << delet;
|
||||
cout << insert << succ_lookup << nosucc_lookup << delet;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
void string_test_aggregate(T map, int runs){
|
||||
void string_test_aggregate(T map, int runs) {
|
||||
std::ofstream output{"results.csv", std::ios_base::app};
|
||||
for (int i = 0; i < runs; ++i){
|
||||
for (int i = 0; i < runs; ++i) {
|
||||
string insert = "\nint_insert, '";
|
||||
string succ_lookup = "\nint_succ_lookup, '";
|
||||
string nosucc_lookup = "\nint_nosucc_lookup, '";
|
||||
string delet = "\nint_delete, '";
|
||||
|
||||
insert += string{name(map)} + "'";
|
||||
succ_lookup += string{name(map)} + "'" ;
|
||||
nosucc_lookup += string{name(map)} +"'" ;
|
||||
delet += string{name(map)} + "'" ;
|
||||
for ( auto size : sizes){
|
||||
insert += string{name(map)} + "'";
|
||||
succ_lookup += string{name(map)} + "'";
|
||||
nosucc_lookup += string{name(map)} + "'";
|
||||
delet += string{name(map)} + "'";
|
||||
for (auto size : sizes) {
|
||||
vector<int> results = string_test(map, size);
|
||||
|
||||
|
||||
insert += ", " + std::to_string(results[0]);
|
||||
succ_lookup += ", " + std::to_string(results[1]);
|
||||
nosucc_lookup +=", " + std::to_string(results[2]);
|
||||
nosucc_lookup += ", " + std::to_string(results[2]);
|
||||
delet += ", " + std::to_string(results[3]);
|
||||
}
|
||||
output << insert << succ_lookup << nosucc_lookup << delet;
|
||||
cout << insert << succ_lookup << nosucc_lookup << delet;
|
||||
output << insert << succ_lookup << nosucc_lookup << delet;
|
||||
cout << insert << succ_lookup << nosucc_lookup << delet;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
@@ -3,10 +3,9 @@
|
||||
#define GENERATOR_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
static std::mt19937 generator(INT32_MAX - 2020);
|
||||
static std::uniform_int_distribution<int> insert_int(1, INT32_MAX * 0.875);
|
||||
static std::uniform_int_distribution<int> noninsert_int(INT32_MAX * 0.875, INT32_MAX);
|
||||
@@ -14,11 +13,12 @@ static std::uniform_int_distribution<int> singlechar(33, 123);
|
||||
|
||||
|
||||
int gen_int();
|
||||
|
||||
int gen_unsuccesfull_int();
|
||||
|
||||
std::string gen_string();
|
||||
|
||||
std::string gen_unsuccesfull_string();
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* GENERATOR_H */
|
@@ -24,27 +24,48 @@
|
||||
#include "./3thparty/parallel_hashmap/phmap.h"
|
||||
#include "./3thparty/emilib/hash_map.hpp"
|
||||
#include "3thparty/robinhood/robin_hood.h"
|
||||
#include <type_traits>
|
||||
|
||||
using std::string;
|
||||
using absl::Hash;
|
||||
using absl::Hash;
|
||||
|
||||
template<class T>
|
||||
void prepare(T& map, int size){
|
||||
void prepare(T& map, int size) {
|
||||
map.reserve(size);
|
||||
}
|
||||
|
||||
void prepare(google::sparse_hash_map<int, int>& map, int size){
|
||||
map.set_deleted_key(-1);
|
||||
void prepare(google::sparse_hash_map<int, int>& map, int size) {
|
||||
map.set_deleted_key(-1);
|
||||
}
|
||||
void prepare(google::sparse_hash_map<string, string>& map, int size){
|
||||
|
||||
void prepare(google::sparse_hash_map<string, string>& map, int size) {
|
||||
map.set_deleted_key("a");
|
||||
}
|
||||
void prepare(google::dense_hash_map<int, int>& map, int size){
|
||||
|
||||
void prepare(google::dense_hash_map<int, int>& map, int size) {
|
||||
map.set_empty_key(0);
|
||||
map.set_deleted_key(-1);
|
||||
}
|
||||
void prepare(google::dense_hash_map<string, string>& map, int size){
|
||||
|
||||
void prepare(google::dense_hash_map<string, string>& map, int size) {
|
||||
map.set_deleted_key("a");
|
||||
map.set_empty_key("");
|
||||
}
|
||||
|
||||
// with abseil hash
|
||||
void prepare(google::sparse_hash_map<int, int, Hash<int>>& map, int size) {
|
||||
map.set_deleted_key(-1);
|
||||
}
|
||||
|
||||
void prepare(google::sparse_hash_map<string, string, Hash<string>>& map, int size) {
|
||||
map.set_deleted_key("a");
|
||||
}
|
||||
|
||||
void prepare(google::dense_hash_map<int, int, Hash<int>>& map, int size) {
|
||||
map.set_empty_key(0);
|
||||
map.set_deleted_key(-1);
|
||||
}
|
||||
|
||||
void prepare(google::dense_hash_map<string, string, Hash<string>>& map, int size) {
|
||||
map.set_deleted_key("a");
|
||||
map.set_empty_key("");
|
||||
}
|
||||
|
@@ -19,8 +19,8 @@ using std::vector;
|
||||
using std::cout;
|
||||
|
||||
|
||||
template <class T>
|
||||
vector<int> int_test(T map, int size){
|
||||
template<class T>
|
||||
vector<int> int_test(T map, int size) {
|
||||
vector<int> results; // insert, lookup, unsuccesful lookup, delete times
|
||||
vector<int> sample_keys; // get a sample of keys to lookup and later delete
|
||||
|
||||
@@ -36,21 +36,21 @@ vector<int> int_test(T map, int size){
|
||||
prepare(testmap, size); // do special actions, such as setting the tombstone marker for other, more exotic hashmaps
|
||||
|
||||
{ // seperate scope, so all_keys gets destroyed. for good measure, empty it too
|
||||
vector<int> all_keys(size - 10000);
|
||||
std::generate(all_keys.begin(), all_keys.end(), gen_int);
|
||||
std::sample(all_keys.begin(), all_keys.end(), std::back_inserter(sample_keys), 10000, generator);
|
||||
vector<int> all_keys(size - 10000);
|
||||
std::generate(all_keys.begin(), all_keys.end(), gen_int);
|
||||
std::sample(all_keys.begin(), all_keys.end(), std::back_inserter(sample_keys), 10000, generator);
|
||||
|
||||
for (auto i : all_keys){
|
||||
testmap.insert({i,i});
|
||||
}
|
||||
all_keys.clear();
|
||||
for (auto i : all_keys) {
|
||||
testmap.insert({i, i});
|
||||
}
|
||||
all_keys.clear();
|
||||
}
|
||||
|
||||
|
||||
// testing vector access times to subtract later
|
||||
time_point<steady_clock> vector_start = steady_clock::now();
|
||||
for (auto i : sample_keys){
|
||||
if (i == -1 ) cout << "WTF"; // should never run, is here so loop doesnt get optimized away
|
||||
for (auto i : sample_keys) {
|
||||
if (i == -1) cout << "WTF"; // should never run, is here so loop doesnt get optimized away
|
||||
}
|
||||
time_point<steady_clock> vector_end = steady_clock::now();
|
||||
auto vector_acces_time = duration_cast<nanoseconds>(vector_end - vector_start);
|
||||
@@ -58,32 +58,32 @@ vector<int> int_test(T map, int size){
|
||||
|
||||
// insertion test
|
||||
time_point<steady_clock> insert_start = steady_clock::now();
|
||||
for (auto key : insert_keys){
|
||||
testmap.insert({key,key});
|
||||
for (auto key : insert_keys) {
|
||||
testmap.insert({key, key});
|
||||
}
|
||||
time_point<steady_clock> insert_end = steady_clock::now();
|
||||
|
||||
auto insert_time = (duration_cast<nanoseconds>(insert_end - insert_start) - vector_acces_time) / 10000 ;
|
||||
auto insert_time = (duration_cast<nanoseconds>(insert_end - insert_start) - vector_acces_time) / 10000;
|
||||
results.push_back(insert_time.count());
|
||||
// remove some memory
|
||||
insert_keys.clear();
|
||||
|
||||
// lookup test
|
||||
time_point<steady_clock> lookup_start = steady_clock::now();
|
||||
for (auto key : sample_keys){
|
||||
if (testmap[key] == 0) cout << "WTF";
|
||||
for (auto key : sample_keys) {
|
||||
if (testmap[key] == 0) cout << "WTF";
|
||||
}
|
||||
time_point<steady_clock> lookup_end = steady_clock::now();
|
||||
auto lookup_time = (duration_cast<nanoseconds>(lookup_end - lookup_start) - vector_acces_time)/10000;
|
||||
auto lookup_time = (duration_cast<nanoseconds>(lookup_end - lookup_start) - vector_acces_time) / 10000;
|
||||
results.push_back(lookup_time.count());
|
||||
|
||||
// unsuccesful lookup test
|
||||
time_point<steady_clock> unlookup_start = steady_clock::now();
|
||||
for (auto key : nonkeys){
|
||||
if (testmap[key] == -1) cout << "WTF";
|
||||
for (auto key : nonkeys) {
|
||||
if (testmap[key] == -1) cout << "WTF";
|
||||
}
|
||||
time_point<steady_clock> unlookup_end = steady_clock::now();
|
||||
auto unlookup_time = (duration_cast<nanoseconds>(unlookup_end - unlookup_start) - vector_acces_time) / 10000 ;
|
||||
auto unlookup_time = (duration_cast<nanoseconds>(unlookup_end - unlookup_start) - vector_acces_time) / 10000;
|
||||
results.push_back(unlookup_time.count());
|
||||
//free some memoru
|
||||
nonkeys.clear();
|
||||
@@ -91,10 +91,10 @@ vector<int> int_test(T map, int size){
|
||||
|
||||
// delete test
|
||||
time_point<steady_clock> delete_start = steady_clock::now();
|
||||
for (auto key : sample_keys){
|
||||
testmap.erase(key);
|
||||
for (auto key : sample_keys) {
|
||||
testmap.erase(key);
|
||||
}
|
||||
|
||||
|
||||
time_point<steady_clock> delete_end = steady_clock::now();
|
||||
auto delete_time = (duration_cast<nanoseconds>(delete_end - delete_start) - vector_acces_time) / 10000;
|
||||
results.push_back(delete_time.count());
|
||||
@@ -104,9 +104,8 @@ vector<int> int_test(T map, int size){
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T>
|
||||
vector<int> string_test(T map, int size){
|
||||
template<class T>
|
||||
vector<int> string_test(T map, int size) {
|
||||
vector<int> results; // insert, lookup, unsuccesful lookup, delete times
|
||||
vector<string> sample_keys; // get a sample of keys to lookup and later delete
|
||||
|
||||
@@ -123,21 +122,21 @@ vector<int> string_test(T map, int size){
|
||||
prepare(testmap, size); // do special actions, such as setting the tombstone marker for other, more exotic hashmaps
|
||||
|
||||
{ // seperate scope, so all_keys gets destroyed. for good measure, empty it too
|
||||
vector<string> all_keys(size - 10000);
|
||||
std::generate(all_keys.begin(), all_keys.end(), gen_string);
|
||||
std::sample(all_keys.begin(), all_keys.end(), std::back_inserter(sample_keys), 10000, generator);
|
||||
vector<string> all_keys(size - 10000);
|
||||
std::generate(all_keys.begin(), all_keys.end(), gen_string);
|
||||
std::sample(all_keys.begin(), all_keys.end(), std::back_inserter(sample_keys), 10000, generator);
|
||||
|
||||
for (auto i : all_keys){
|
||||
testmap.insert({i,i});
|
||||
}
|
||||
all_keys.clear();
|
||||
for (auto i : all_keys) {
|
||||
testmap.insert({i, i});
|
||||
}
|
||||
all_keys.clear();
|
||||
}
|
||||
|
||||
|
||||
// testing vector access times to subtract later
|
||||
time_point<steady_clock> vector_start = steady_clock::now();
|
||||
for (auto i : sample_keys){
|
||||
if (i == "" ) cout << "WTF"; // should never run, is here so loop doesnt get optimized away
|
||||
for (auto i : sample_keys) {
|
||||
if (i == "") cout << "WTF"; // should never run, is here so loop doesnt get optimized away
|
||||
}
|
||||
time_point<steady_clock> vector_end = steady_clock::now();
|
||||
auto vector_acces_time = duration_cast<nanoseconds>(vector_end - vector_start);
|
||||
@@ -145,42 +144,42 @@ vector<int> string_test(T map, int size){
|
||||
|
||||
// insertion test
|
||||
time_point<steady_clock> insert_start = steady_clock::now();
|
||||
for (auto key : insert_keys){
|
||||
testmap.insert({key,key});
|
||||
for (auto key : insert_keys) {
|
||||
testmap.insert({key, key});
|
||||
}
|
||||
time_point<steady_clock> insert_end = steady_clock::now();
|
||||
|
||||
auto insert_time = (duration_cast<nanoseconds>(insert_end - insert_start) - vector_acces_time) / 10000 ;
|
||||
auto insert_time = (duration_cast<nanoseconds>(insert_end - insert_start) - vector_acces_time) / 10000;
|
||||
results.push_back(insert_time.count());
|
||||
// remove some memory
|
||||
insert_keys.clear();
|
||||
|
||||
// lookup test
|
||||
time_point<steady_clock> lookup_start = steady_clock::now();
|
||||
for (auto key : sample_keys){
|
||||
if (testmap[key] == "") cout << "WTF";
|
||||
for (auto key : sample_keys) {
|
||||
if (testmap[key] == "") cout << "WTF";
|
||||
}
|
||||
time_point<steady_clock> lookup_end = steady_clock::now();
|
||||
auto lookup_time = (duration_cast<nanoseconds>(lookup_end - lookup_start) - vector_acces_time)/10000;
|
||||
auto lookup_time = (duration_cast<nanoseconds>(lookup_end - lookup_start) - vector_acces_time) / 10000;
|
||||
results.push_back(lookup_time.count());
|
||||
|
||||
// unsuccesful lookup test
|
||||
time_point<steady_clock> unlookup_start = steady_clock::now();
|
||||
for (auto key : nonkeys){
|
||||
if (testmap[key] == "a") cout << "WTF";
|
||||
for (auto key : nonkeys) {
|
||||
if (testmap[key] == "a") cout << "WTF";
|
||||
}
|
||||
time_point<steady_clock> unlookup_end = steady_clock::now();
|
||||
auto unlookup_time = (duration_cast<nanoseconds>(unlookup_end - unlookup_start) - vector_acces_time) / 10000 ;
|
||||
auto unlookup_time = (duration_cast<nanoseconds>(unlookup_end - unlookup_start) - vector_acces_time) / 10000;
|
||||
results.push_back(unlookup_time.count());
|
||||
//free some memoru
|
||||
nonkeys.clear();
|
||||
|
||||
// delete test
|
||||
time_point<steady_clock> delete_start = steady_clock::now();
|
||||
for (auto key : sample_keys){
|
||||
testmap.erase(key);
|
||||
for (auto key : sample_keys) {
|
||||
testmap.erase(key);
|
||||
}
|
||||
|
||||
|
||||
time_point<steady_clock> delete_end = steady_clock::now();
|
||||
auto delete_time = (duration_cast<nanoseconds>(delete_end - delete_start) - vector_acces_time) / 10000;
|
||||
results.push_back(delete_time.count());
|
||||
|
284
src/main.cpp
284
src/main.cpp
@@ -1,114 +1,186 @@
|
||||
#include "./includes/3thparty/CLI11.hpp"
|
||||
#include "./includes/aggregate_tests.h"
|
||||
#include <iostream>
|
||||
|
||||
// // we can use typedefs and switch statements for the map implementations
|
||||
// // we can add some cli handling so we can specify which maps to tests (or all)
|
||||
// 3. folly F14ValueMap // lots of dependencies, even tho it really seems cool
|
||||
// 4. folly F14NodeMap
|
||||
// 5. Tessil/ordered-map [n] something is wrong with this one, verrrrry slow
|
||||
// 6. Tessil/array-hash[n] (not with a small modification of the insert function)
|
||||
|
||||
typedef std::unordered_map<int, int> intmap;
|
||||
typedef std::unordered_map<string, string> stringmap;
|
||||
string choicetext = "Select implementation to test: '-i 1 2 3 4' or '-i 1,2,3'. Default is all \n"
|
||||
"1. std::unordered_hashmap(1) \n"
|
||||
"2. google:: hashmaps(2) \n"
|
||||
"3. abseil's absl:: hashmaps(2) \n"
|
||||
"4. tessil's tsl:: hashmaps(3) \n"
|
||||
"5. boost::unordered_map(1) \n"
|
||||
"6. Skarupke ska:: hashmaps(3) \n"
|
||||
"7. greg7ndp's phmap:: hashmaps(2) \n"
|
||||
"8. emilk's emilib:: hashmap(1) \n"
|
||||
"9. martin's robin_hood:: hashmaps(2) \n";
|
||||
|
||||
// // google sparse
|
||||
// typedef google::sparse_hash_map<int, int> intmap;
|
||||
// typedef google::sparse_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // google dense
|
||||
// typedef google::dense_hash_map<int, int> intmap;
|
||||
// typedef google::dense_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // abseil nodehashmap
|
||||
// typedef absl::node_hash_map<int, int> intmap;
|
||||
// typedef absl::node_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // flat hashmap
|
||||
// typedef absl::flat_hash_map<int, int> intmap;
|
||||
// typedef absl::flat_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // tessil flat hashmap
|
||||
// typedef tsl::sparse_map<int, int> intmap;
|
||||
// typedef tsl::sparse_map<string,string> stringmap;
|
||||
//
|
||||
// // Tessil tsl::array_map
|
||||
// typedef tsl::array_map<int, int> intmap;
|
||||
// typedef tsl::array_map<string,string> stringmap;
|
||||
//
|
||||
// // Tessil tsl::ordered_map
|
||||
// typedef tsl::ordered_map<int, int> intmap;
|
||||
// typedef tsl::ordered_map<string,string> stringmap;
|
||||
//
|
||||
// // Tessil tsl::robin_map
|
||||
// typedef tsl::robin_map<int, int> intmap;
|
||||
// typedef tsl::robin_map<string,string> stringmap;
|
||||
//
|
||||
// // Tessil hopscotch_map
|
||||
// typedef tsl::hopscotch_map<int, int> intmap;
|
||||
// typedef tsl::hopscotch_map<string,string> stringmap;
|
||||
//
|
||||
// // Boost::unordered_map
|
||||
// typedef boost::unordered_map<int, int> intmap;
|
||||
// typedef boost::unordered_map<string,string> stringmap;
|
||||
//
|
||||
// // skarupke's unordered map
|
||||
// typedef ska::unordered_map<int, int> intmap;
|
||||
// typedef ska::unordered_map<string,string> stringmap;
|
||||
//
|
||||
// // skarupke's bytell hash map
|
||||
// typedef ska::bytell_hash_map<int, int> intmap;
|
||||
// typedef ska::bytell_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // skarupke's flat hash map
|
||||
// typedef ska::flat_hash_map<int, int> intmap;
|
||||
// typedef ska::flat_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // greg7mdp's flat hash map
|
||||
// typedef phmap::parallel_flat_hash_map<int, int> intmap;
|
||||
// typedef phmap::parallel_flat_hash_map<string,string> stringmap;
|
||||
//
|
||||
// // greg7mdp's hash map
|
||||
// typedef phmap::parallel_node_hash_map<int, int> intmap;
|
||||
// typedef phmap::parallel_node_hash_map<string,string> stringmap;
|
||||
// // emilib's hash map
|
||||
// typedef emilib::HashMap<int, int> intmap;
|
||||
// typedef emilib::HashMap<string,string> stringmap;
|
||||
// // martin flat map
|
||||
// typedef robin_hood::unordered_flat_map<int, int> intmap;
|
||||
// typedef robin_hood::unordered_flat_map<string,string> stringmap;
|
||||
// martin flat map
|
||||
// typedef robin_hood::unordered_node_map<int, int> intmap;
|
||||
// typedef robin_hood::unordered_node_map<string,string> stringmap;
|
||||
int main(int argc, char** argv) {
|
||||
CLI::App app{"Hashmap benchmarks"};
|
||||
vector<int> hashmaps = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
app.add_option("-i,--implementation", hashmaps, choicetext )->delimiter(',');
|
||||
bool use_abseil_hash = false;
|
||||
app.add_option("-a,--abseil", use_abseil_hash, "use absl::Hash, default is false");
|
||||
int runs = 1;
|
||||
app.add_option("-r,--runs", runs, "total runs for each map, default is 1");
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
|
||||
/* test takes 2hrs for 30 runs for unordered_map hashmap
|
||||
// if the other maps have about the same operation times, it'll
|
||||
// take around ~40hrs total ************
|
||||
// priorities are that the interface must be the same/similar to unordered_map
|
||||
// and that we don't have to jump through hoops to get it to work
|
||||
1. Google dense_hash_map [y] https://github.com/sparsehash/sparsehash
|
||||
2. Google sparse_hash_map [y]
|
||||
3. abseil node_hash_map [y] https://abseil.io/docs/cpp/tools/cmake-installs
|
||||
4. abseil flat_hash_map [y]
|
||||
5. Tessil/sparse-map/ [y] header only implementation for all tessil
|
||||
6. Tessil/hopscotch-map[y]
|
||||
7. tessil/robin-map[y] [y]
|
||||
8. Boost unordered_map [y] just install boost with your package manager
|
||||
9. skarupke/flat_hash_map [y] header only implementation
|
||||
10. skarupke /bytell_hash_map [y]
|
||||
11. skarupke/unordered_map [y]
|
||||
12. greg7mdp/parallel-hashmap/paralel_flat [y] header only
|
||||
13. greg7mdp/parallel-hashmap/paralel_node [y]
|
||||
17. emilk/emilib emilib::hashmap [y] header only
|
||||
18. martinus robin_hood::unordered_node_map [y]
|
||||
19. martinus/robin_hood/ flatmap [y]
|
||||
|
||||
3. folly F14ValueMap // lots of dependencies, even tho it really seems cool
|
||||
4. folly F14NodeMap
|
||||
5. Tessil/ordered-map [n] something is wrong with this one, verrrrry slow
|
||||
6. Tessil/array-hash[n] (not with a small modification of the insert function)
|
||||
*/
|
||||
|
||||
int main() {
|
||||
time_point<steady_clock> start_test = steady_clock::now();
|
||||
int_test_aggregate(intmap{}, 2);
|
||||
string_test_aggregate(stringmap{}, 2);
|
||||
if (use_abseil_hash) {
|
||||
for (auto i : hashmaps) {
|
||||
switch (i) {
|
||||
case 1: {
|
||||
int_test_aggregate(std::unordered_map<int, int>{}, runs);
|
||||
string_test_aggregate(std::unordered_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
int_test_aggregate(google::sparse_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(google::sparse_hash_map<string, string>{}, runs);
|
||||
int_test_aggregate(google::dense_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(google::dense_hash_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int_test_aggregate(absl::node_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(absl::node_hash_map<string, string>{}, runs);
|
||||
int_test_aggregate(absl::flat_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(absl::flat_hash_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int_test_aggregate(tsl::sparse_map<int, int>{}, runs);
|
||||
string_test_aggregate(tsl::sparse_map<string, string>{}, runs);
|
||||
// int_test_aggregate(tsl::array_map<int, int>{}, runs);
|
||||
// string_test_aggregate(tsl::array_map<string, string>{}, runs);
|
||||
// int_test_aggregate(tsl::ordered_map<int, int>{}, runs);
|
||||
// string_test_aggregate(tsl::ordered_map<string, string>{}, runs);
|
||||
int_test_aggregate(tsl::robin_map<int, int>{}, runs);
|
||||
string_test_aggregate(tsl::robin_map<string, string>{}, runs);
|
||||
int_test_aggregate(tsl::hopscotch_map<int, int>{}, runs);
|
||||
string_test_aggregate(tsl::hopscotch_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
int_test_aggregate(boost::unordered_map<int, int>{}, runs);
|
||||
string_test_aggregate(boost::unordered_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
int_test_aggregate(ska::unordered_map<int, int>{}, runs);
|
||||
string_test_aggregate(ska::unordered_map<string, string>{}, runs);
|
||||
int_test_aggregate(ska::bytell_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(ska::bytell_hash_map<string, string>{}, runs);
|
||||
int_test_aggregate(ska::flat_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(ska::flat_hash_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
int_test_aggregate(phmap::parallel_flat_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(phmap::parallel_flat_hash_map<string, string>{}, runs);
|
||||
int_test_aggregate(phmap::parallel_node_hash_map<int, int>{}, runs);
|
||||
string_test_aggregate(phmap::parallel_node_hash_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
int_test_aggregate(emilib::HashMap<int, int>{}, runs);
|
||||
string_test_aggregate(emilib::HashMap<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
int_test_aggregate(robin_hood::unordered_flat_map<int, int>{}, runs);
|
||||
string_test_aggregate(robin_hood::unordered_flat_map<string, string>{}, runs);
|
||||
int_test_aggregate(robin_hood::unordered_node_map<int, int>{}, runs);
|
||||
string_test_aggregate(robin_hood::unordered_node_map<string, string>{}, runs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
for (auto i : hashmaps) {
|
||||
switch (i) {
|
||||
case 1: {
|
||||
int_test_aggregate(std::unordered_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(std::unordered_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
int_test_aggregate(google::sparse_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(google::sparse_hash_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(google::dense_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(google::dense_hash_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int_test_aggregate(absl::node_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(absl::node_hash_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(absl::flat_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(absl::flat_hash_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int_test_aggregate(tsl::sparse_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(tsl::sparse_map<string, string, Hash<string>>{}, runs);
|
||||
// int_test_aggregate(tsl::array_map<int, int, Hash<int>>{}, runs);
|
||||
// string_test_aggregate(tsl::array_map<string, string, Hash<string>>{}, runs);
|
||||
// int_test_aggregate(tsl::ordered_map<int, int, Hash<int>>{}, runs);
|
||||
// string_test_aggregate(tsl::ordered_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(tsl::robin_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(tsl::robin_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(tsl::hopscotch_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(tsl::hopscotch_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
int_test_aggregate(boost::unordered_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(boost::unordered_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
int_test_aggregate(ska::unordered_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(ska::unordered_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(ska::bytell_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(ska::bytell_hash_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(ska::flat_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(ska::flat_hash_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
int_test_aggregate(phmap::parallel_flat_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(phmap::parallel_flat_hash_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(phmap::parallel_node_hash_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(phmap::parallel_node_hash_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
int_test_aggregate(emilib::HashMap<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(emilib::HashMap<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
int_test_aggregate(robin_hood::unordered_flat_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(robin_hood::unordered_flat_map<string, string, Hash<string>>{}, runs);
|
||||
int_test_aggregate(robin_hood::unordered_node_map<int, int, Hash<int>>{}, runs);
|
||||
string_test_aggregate(robin_hood::unordered_node_map<string, string, Hash<string>>{}, runs);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
time_point<steady_clock> end_test = steady_clock::now();
|
||||
std::cout << "\n\n 30 runs for all tests for 1 map: " << duration_cast<seconds>(end_test-start_test).count() << " seconds\n\n";
|
||||
|
||||
std::cout << "\n\n 30 runs for all tests for 1 map: " << duration_cast<seconds>(end_test - start_test).count()
|
||||
<< " seconds\n\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user