diff options
| author | Tyge Løvset <[email protected]> | 2022-04-24 20:50:53 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-04-24 20:50:53 +0200 |
| commit | 81b541b85f85b48660ceb461b851f1fb09d68344 (patch) | |
| tree | 909d8c7cdeb5fc6daad007d4cd46e65d4af1c6e4 /benchmarks/misc | |
| parent | 91385d449d03145cfe8cc91f2704d4b24c63d37e (diff) | |
| parent | 8aeec88bd7f15069a388f7fc8fe0008af4d1ab44 (diff) | |
| download | STC-modified-81b541b85f85b48660ceb461b851f1fb09d68344.tar.gz STC-modified-81b541b85f85b48660ceb461b851f1fb09d68344.zip | |
Merge pull request #21 from tylov/keyval
Version 3.5 RC
Diffstat (limited to 'benchmarks/misc')
| -rw-r--r-- | benchmarks/misc/sso_bench.c | 52 | ||||
| -rw-r--r-- | benchmarks/misc/sso_bench.cpp (renamed from benchmarks/misc/sso_bench2.cpp) | 20 | ||||
| -rw-r--r-- | benchmarks/misc/string_bench.c | 153 | ||||
| -rw-r--r-- | benchmarks/misc/string_bench.cpp | 199 | ||||
| -rw-r--r-- | benchmarks/misc/string_bench_STC.cpp | 298 | ||||
| -rw-r--r-- | benchmarks/misc/string_bench_STD.cpp | 370 |
6 files changed, 678 insertions, 414 deletions
diff --git a/benchmarks/misc/sso_bench.c b/benchmarks/misc/sso_bench.c deleted file mode 100644 index 450884f3..00000000 --- a/benchmarks/misc/sso_bench.c +++ /dev/null @@ -1,52 +0,0 @@ -// https://gobyexample.com/maps -#include <stc/alt/cstr.h> -#define i_type Map -#define i_key_str -#define i_val int -#include <stc/cmap.h> -#define i_type Vec -#define i_val_str -#include <stc/cvec.h> - -#include <time.h> -#include <stc/crandom.h> - -void rndstr(char buf[64], int max) { - unsigned n = crandom() % max; - static char chr[64] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; - c_forrange (i, n) - buf[i] = chr[crandom() & 63]; - buf[n] = '\0'; -} - -enum {N = 10000000}; - -int main(void) { - - c_auto (Vec, vec) - c_auto (Map, map) { - char buf[128]; - - csrandom(time(NULL)); - printf("map\n"); - clock_t t0 = clock(), t1, t2; - c_forrange (i, int, N) { - rndstr(buf, 64); - Map_emplace(&map, buf, i); - } - t1 = clock(); - printf("vec\n"); - c_apply_cnt(v, Vec_push(&vec, cstr_clone(v->first)), Map, map); - t2 = clock(); - puts("map items:"); - int k = 0; - c_forpair (k, v, Map, map) - if (k++ == 5) break; else printf(" %s: %d\n", cstr_str(&_.k), _.v); - puts("vec items:"); - k = 0; - c_foreach (i, Vec, vec) - if (k++ == 5) break; else printf(" %s\n", cstr_str(i.ref)); - - printf("\nmap insert: %d ms\nvec pushes: %d ms\n", (int)((t1 - t0)*10000/CLOCKS_PER_SEC), (int)((t2 - t1)*10000/CLOCKS_PER_SEC)); - } -} diff --git a/benchmarks/misc/sso_bench2.cpp b/benchmarks/misc/sso_bench.cpp index 87b701b5..5ff54be9 100644 --- a/benchmarks/misc/sso_bench2.cpp +++ b/benchmarks/misc/sso_bench.cpp @@ -2,7 +2,6 @@ #include <iostream> #include <vector> #include <chrono> -#define STC_USE_SSO 1 #define i_type svec #define i_val_str #include <stc/cstack.h> @@ -33,7 +32,7 @@ static void sromutrio(uint64_t seed) { static const char CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=+-"; static const int BENCHMARK_SIZE = 5000000; -static const int MAX_STRING_LENGTH = 20; +static const int MAX_STRING_LENGTH = 30; using time_point = std::chrono::high_resolution_clock::time_point; @@ -44,7 +43,7 @@ void addRandomString_STD(std::vector<std::string>& vec, const int length) { p[i] = CHARS[romutrio() & 63]; } s.append(s); - vec.push_back(s); + vec.push_back(std::move(s)); } void addRandomString_STC(svec& vec, const int length) { @@ -54,7 +53,7 @@ void addRandomString_STC(svec& vec, const int length) { p[i] = CHARS[romutrio() & 63]; } cstr_append_s(&s, s); - svec_push(&vec, s); + svec_push_back(&vec, s); } template <class L, typename R> @@ -75,7 +74,8 @@ void benchmark(L& vec, const int length, R addRandomString) { int main() { - sromutrio(1234); + uint64_t seed = 4321; + sromutrio(seed); std::cerr << "length\ttime\tstd::string\n"; for (int k = 0; k < 4; k++) { std::vector<std::string> vec; vec.reserve(BENCHMARK_SIZE); @@ -83,7 +83,7 @@ int main() { std::cout << '\t' << vec[0] << '\n'; } - sromutrio(1234); + sromutrio(seed); std::cerr << "\nlength\ttime\tSTC string\n"; for (int k = 0; k < 4; k++) { svec vec = svec_with_capacity(BENCHMARK_SIZE); @@ -92,7 +92,7 @@ int main() { svec_drop(&vec); } - sromutrio(1234); + sromutrio(seed); std::cerr << "length\ttime\tstd::string\n"; for (int length = 1; length <= MAX_STRING_LENGTH; length++) { std::vector<std::string> vec; vec.reserve(BENCHMARK_SIZE); @@ -100,7 +100,7 @@ int main() { std::cout << '\t' << vec[0] << '\n'; } - sromutrio(1234); + sromutrio(seed); std::cerr << "\nlength\ttime\tSTC string\n"; for (int length = 1; length <= MAX_STRING_LENGTH; length++) { svec vec = svec_with_capacity(BENCHMARK_SIZE); @@ -109,7 +109,7 @@ int main() { svec_drop(&vec); } - std::cerr << "size std::string : " << sizeof(std::string) << std::endl - << "size STC string : " << sizeof(cstr) << std::endl; + std::cerr << "sizeof std::string : " << sizeof(std::string) << std::endl + << "sizeof STC string : " << sizeof(cstr) << std::endl; return 0; } diff --git a/benchmarks/misc/string_bench.c b/benchmarks/misc/string_bench.c deleted file mode 100644 index fb2a70b2..00000000 --- a/benchmarks/misc/string_bench.c +++ /dev/null @@ -1,153 +0,0 @@ -// https://www.codeproject.com/Tips/5255442/Cplusplus14-20-Heterogeneous-Lookup-Benchmark
-// https://github.com/shaovoon/cpp_hetero_lookup_bench
-
-#include <time.h>
-
-#define i_val_str
-#include <stc/cvec.h>
-
-#define i_key_str
-#define i_val size_t
-#include <stc/cmap.h>
-
-#define i_key_str
-#define i_val size_t
-#include <stc/csmap.h>
-
-
-cvec_str read_file(const char* name)
-{
- cvec_str data = cvec_str_init();
- c_auto (cstr, line)
- c_autovar (FILE* f = fopen(name, "r"), fclose(f))
- while (cstr_getline(&line, f))
- cvec_str_emplace_back(&data, cstr_str(&line));
- return data;
-}
-
-void initShortStringVec(cvec_str* vs)
-{
- cvec_str_clear(vs);
-
- *vs = read_file("names.txt");
- size_t lengths = 0;
- c_foreach (i, cvec_str, *vs)
- {
- cstr_append_s(i.ref, *i.ref);
- cstr_append_s(i.ref, *i.ref);
- lengths += cstr_size(*i.ref);
- }
- printf("avg len: %f\n", (float)lengths / cvec_str_size(*vs));
-}
-
-void initLongStringVec(cvec_str* vs)
-{
- cvec_str_clear(vs);
- *vs = read_file("names.txt");
- cstr* s = vs->data;
- size_t lengths = 0;
- cstr_append_s(s, s[1]);
- cstr_append_s(s, s[2]);
- cstr_append_s(s, s[3]);
- for (int i=1; i < cvec_str_size(*vs); ++i)
- {
- cstr* t = vs->data + i;
- cstr_append_s(t, *t);
- cstr_append_s(t, *t);
- cstr_append_s(t, *s);
- cstr_append_s(t, *t);
- cstr_append_s(t, *t);
- lengths += cstr_size(*t);
- }
- printf("avg len: %f\n", (float)lengths / cvec_str_size(*vs));
-}
-
-struct Maps {
- csmap_str* snormal;
- cmap_str* unormal;
-};
-
-void initMaps(cvec_str vs, struct Maps maps)
-{
- csmap_str_clear(maps.snormal);
- cmap_str_clear(maps.unormal);
-
- for (size_t i = 0; i < cvec_str_size(vs); ++i)
- {
- cstr str = *cvec_str_at(&vs, i);
- csmap_str_insert(maps.snormal, cstr_clone(str), i);
- cmap_str_insert(maps.unormal, cstr_clone(str), i);
- }
-}
-
-void benchmark(cvec_str vec_string, struct Maps maps);
-
-static const size_t MAX_LOOP = 2000;
-
-int main()
-{
- c_auto (cvec_str, vec_string)
- c_auto (csmap_str, snormal)
- c_auto (cmap_str, unormal)
- {
- struct Maps maps = { &snormal, &unormal };
-
- initShortStringVec(&vec_string);
- initMaps(vec_string, maps);
-
- puts("Short String Benchmark");
- puts("======================");
-
- benchmark(vec_string, maps);
-
- puts("\nLong String Benchmark");
- puts("======================");
-
- initLongStringVec(&vec_string);
- initMaps(vec_string, maps);
-
- benchmark(vec_string, maps);
- }
-}
-
-void benchmark(cvec_str vec_string, struct Maps maps)
-{
- size_t grandtotal = 0;
- size_t total;
- clock_t stopwatch;
-
- total = 0;
- printf("%32s", "Trans Map with char*");
- stopwatch = clock();
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- csmap_str_iter it, end = csmap_str_end(maps.snormal);
- for (size_t j = 0; j < cvec_str_size(vec_string); ++j)
- {
- csmap_str_find_it(maps.snormal, cstr_str(&vec_string.data[j]), &it);
- if (it.ref != end.ref)
- total += it.ref->second;
- }
- }
- grandtotal += total;
- printf(" timing:%5.0fms\n", (clock() - stopwatch) / (float)CLOCKS_PER_SEC * 1000.0f);
-
-
- total = 0;
- printf("%32s", "Trans Unord Map with char*");
- stopwatch = clock();
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- cmap_str_iter it, end = cmap_str_end(maps.unormal);
- for (size_t j = 0; j < cvec_str_size(vec_string); ++j)
- {
- it = cmap_str_find(maps.unormal, cstr_str(&vec_string.data[j]));
- if (it.ref != end.ref)
- total += it.ref->second;
- }
- }
- grandtotal += total;
- printf(" timing:%5.0fms\n", (clock() - stopwatch) / (float)CLOCKS_PER_SEC * 1000.0f);
-
- printf("C grandtotal: %" PRIuMAX " <--- Ignore this\n", grandtotal);
-}
diff --git a/benchmarks/misc/string_bench.cpp b/benchmarks/misc/string_bench.cpp deleted file mode 100644 index 65bf7a0e..00000000 --- a/benchmarks/misc/string_bench.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// https://www.codeproject.com/Tips/5255442/Cplusplus14-20-Heterogeneous-Lookup-Benchmark
-// https://github.com/shaovoon/cpp_hetero_lookup_bench
-
-#include <iostream>
-#include <iomanip>
-#include <chrono>
-#include <string>
-#include <vector>
-#include <map>
-#include <unordered_map>
-
-#define i_val_str
-#include <stc/cvec.h>
-
-
-std::vector<std::string> read_file(const char* name)
-{
- std::vector<std::string> data;
- c_auto (cstr, line)
- c_autovar (FILE* f = fopen(name, "r"), fclose(f))
- while (cstr_getline(&line, f))
- data.emplace_back(cstr_str(&line));
- return data;
-}
-
-class timer
-{
-public:
- timer() = default;
- void start(const std::string& text_)
- {
- text = text_;
- begin = std::chrono::high_resolution_clock::now();
- }
- void stop()
- {
- auto end = std::chrono::high_resolution_clock::now();
- auto dur = end - begin;
- auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
- std::cout << std::setw(32) << text << " timing:" << std::setw(5) << ms << "ms" << std::endl;
- }
-
-private:
- std::string text;
- std::chrono::high_resolution_clock::time_point begin;
-};
-
-void initShortStringVec(std::vector<std::string>& vs)
-{
- vs.clear();
- vs = read_file("names.txt");
- size_t num = 0;
-
- for (size_t i = 0; i < vs.size(); ++i)
- {
- num += vs[i].size();
- }
- printf("avg len: %f\n", (float)num / vs.size());
-}
-
-void initLongStringVec(std::vector<std::string>& vs)
-{
- vs.clear();
- vs = read_file("names.txt");
- size_t num = 0;
- vs[0] += vs[1];
- vs[0] += vs[2];
- vs[0] += vs[3];
- for (size_t i = 1; i < vs.size(); ++i)
- {
- vs[i] += vs[i];
- vs[i] += vs[i];
- vs[i] += vs[0];
- vs[i] += vs[i];
- vs[i] += vs[i];
- num += vs[i].size();
- }
- printf("avg len: %f\n", (float)num / vs.size());
-}
-
-void initMapNormal(const std::vector<std::string>& vs,
- std::map<std::string, size_t>& mapNormal,
- std::unordered_map<std::string, size_t>& unordmapNormal)
-{
- mapNormal.clear();
- unordmapNormal.clear();
- for (size_t i = 0; i < vs.size(); ++i)
- {
- mapNormal.insert(std::make_pair(vs.at(i), i));
- unordmapNormal.insert(std::make_pair(vs.at(i), i));
- }
-}
-/*
-struct string_hash {
- using is_transparent = void;
- using hash_type = std::hash<std::string_view>; // just a helper local type
- size_t operator()(const std::string& txt) const { return hash_type{}(txt); }
- size_t operator()(const char* txt) const { return hash_type{}(txt); }
-};*/
-
-void benchmark(
- const std::vector<std::string>& vec_string,
- const std::map<std::string, size_t>& mapNormal,
- const std::unordered_map<std::string, size_t>& unordmapNormal);
-
-const size_t MAX_LOOP = 2000;
-
-int main()
-{
- std::vector<std::string> vec_string;
-
- std::map<std::string, size_t> mapNormal;
- std::unordered_map<std::string, size_t> unordmapNormal;
-
- initShortStringVec(vec_string);
- initMapNormal(vec_string, mapNormal, unordmapNormal);
-
- std::cout << "Short String Benchmark" << std::endl;
- std::cout << "======================" << std::endl;
-
- benchmark(vec_string, mapNormal, unordmapNormal);
-
- std::cout << "Long String Benchmark" << std::endl;
- std::cout << "=====================" << std::endl;
-
- initLongStringVec(vec_string);
- initMapNormal(vec_string, mapNormal, unordmapNormal);
-
- benchmark(vec_string, mapNormal, unordmapNormal);
- return 0;
-}
-
-void benchmark(
- const std::vector<std::string>& vec_string,
- const std::map<std::string, size_t>& mapNormal,
- const std::unordered_map<std::string, size_t>& unordmapNormal)
-{
- size_t grandtotal = 0;
- size_t total = 0;
- timer stopwatch;
-
- total = 0;
- stopwatch.start("Normal Map with string");
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- for (size_t j = 0; j < vec_string.size(); ++j)
- {
- const auto& it = mapNormal.find(vec_string[j]);
- if(it!=mapNormal.cend())
- total += it->second;
- }
- }
- grandtotal += total;
- stopwatch.stop();
-
- total = 0;
- stopwatch.start("Normal Map with char*");
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- for (size_t j = 0; j < vec_string.size(); ++j)
- {
- const auto& it = mapNormal.find(vec_string[j].c_str());
- if (it != mapNormal.cend())
- total += it->second;
- }
- }
- grandtotal += total;
- stopwatch.stop();
-
- total = 0;
- stopwatch.start("Normal Unord Map with string");
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- for (size_t j = 0; j < vec_string.size(); ++j)
- {
- const auto& it = unordmapNormal.find(vec_string[j]);
- if (it != unordmapNormal.cend())
- total += it->second;
- }
- }
- grandtotal += total;
- stopwatch.stop();
-
- total = 0;
- stopwatch.start("Normal Unord Map with char*");
- for (size_t i = 0; i < MAX_LOOP; ++i)
- {
- for (size_t j = 0; j < vec_string.size(); ++j)
- {
- const auto& it = unordmapNormal.find(vec_string[j].c_str());
- if (it != unordmapNormal.cend())
- total += it->second;
- }
- }
- grandtotal += total;
- stopwatch.stop();
-
- std::cout << "C++ grandtotal:" << grandtotal << " <--- Ignore this\n" << std::endl;
-}
\ No newline at end of file diff --git a/benchmarks/misc/string_bench_STC.cpp b/benchmarks/misc/string_bench_STC.cpp new file mode 100644 index 00000000..ed0e3243 --- /dev/null +++ b/benchmarks/misc/string_bench_STC.cpp @@ -0,0 +1,298 @@ +// https://www.codeproject.com/Tips/5255442/Cplusplus14-20-Heterogeneous-Lookup-Benchmark +// https://github.com/shaovoon/cpp_hetero_lookup_bench + +#include <iostream> +#include <iomanip> +#include <chrono> +#include <stc/cstr.h> // string +#include <stc/csview.h> // string_view + +#define i_key_str +#include <stc/cvec.h> // vec of cstr with const char* lookup + +#define i_type cvec_sv // override default type name (cvec_csview) +#define i_key csview +#define i_cmp csview_cmp +#include <stc/cvec.h> // cvec_vs: vec of csview + +#define i_key_str +#define i_val size_t +#include <stc/csmap.h> // sorted map of cstr, const char* lookup + +#define i_key_ssv +#define i_val size_t +#include <stc/csmap.h> // sorted map of cstr, csview lookup + +#define i_key_str +#define i_val size_t +#include <stc/cmap.h> // unordered map of cstr, const char* lookup + +#define i_key_ssv +#define i_val size_t +#include <stc/cmap.h> // unordered map of cstr, csview lookup + + +cvec_str read_file(const char* name) +{ + cvec_str data = cvec_str_init(); + c_auto (cstr, line) + c_autovar (FILE* f = fopen(name, "r"), fclose(f)) + while (cstr_getline(&line, f)) + cvec_str_emplace_back(&data, cstr_str(&line)); + return data; +} + +class timer +{ +public: + timer() = default; + void start(const std::string& text_) + { + text = text_; + begin = std::chrono::high_resolution_clock::now(); + } + void stop() + { + auto end = std::chrono::high_resolution_clock::now(); + auto dur = end - begin; + auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count(); + std::cout << std::setw(32) << text << " timing:" << std::setw(5) << ms << "ms" << std::endl; + } + +private: + std::string text; + std::chrono::high_resolution_clock::time_point begin; +}; + +void initShortStringVec(cvec_str* vs, cvec_sv* vsv) +{ + cvec_str_clear(vs); + cvec_sv_clear(vsv); + + *vs = read_file("names.txt"); +/* + cvec_str_emplace_back(vs, "Susan"); + cvec_str_emplace_back(vs, "Jason"); + cvec_str_emplace_back(vs, "Lily"); + cvec_str_emplace_back(vs, "Michael"); + cvec_str_emplace_back(vs, "Mary"); + + cvec_str_emplace_back(vs, "Jerry"); + cvec_str_emplace_back(vs, "Jenny"); + cvec_str_emplace_back(vs, "Klaus"); + cvec_str_emplace_back(vs, "Celine"); + cvec_str_emplace_back(vs, "Kenny"); + + cvec_str_emplace_back(vs, "Kelly"); + cvec_str_emplace_back(vs, "Jackson"); + cvec_str_emplace_back(vs, "Mandy"); + cvec_str_emplace_back(vs, "Terry"); + cvec_str_emplace_back(vs, "Sandy"); + + cvec_str_emplace_back(vs, "Billy"); + cvec_str_emplace_back(vs, "Cindy"); + cvec_str_emplace_back(vs, "Phil"); + cvec_str_emplace_back(vs, "Lindy"); + cvec_str_emplace_back(vs, "David"); +*/ + size_t num = 0; + c_foreach (i, cvec_str, *vs) + { + cvec_sv_push_back(vsv, csview_from_s(i.ref)); + num += cstr_size(*i.ref); + } + std::cout << "num strings: " << cvec_sv_size(*vsv) << std::endl; + std::cout << "avg str len: " << num / (float)cvec_sv_size(*vsv) << std::endl; +} + +void initLongStringVec(cvec_str* vs, cvec_sv* vsv) +{ + cvec_str_clear(vs); + cvec_sv_clear(vsv); + + *vs = read_file("names.txt"); + c_foreach (i, cvec_str, *vs) { + cstr_append_s(i.ref, *i.ref); + cstr_append_s(i.ref, *i.ref); + cstr_append_s(i.ref, *i.ref); + } +/* + cvec_str_emplace_back(vs, "Susan Susan Susan Susan Susan Susan"); + cvec_str_emplace_back(vs, "Jason Jason Jason Jason Jason Jason"); + cvec_str_emplace_back(vs, "Lily Lily Lily Lily Lily Lily"); + cvec_str_emplace_back(vs, "Michael Michael Michael Michael Michael Michael"); + cvec_str_emplace_back(vs, "Mary Mary Mary Mary Mary Mary"); + + cvec_str_emplace_back(vs, "Jerry Jerry Jerry Jerry Jerry Jerry"); + cvec_str_emplace_back(vs, "Jenny Jenny Jenny Jenny Jenny Jenny"); + cvec_str_emplace_back(vs, "Klaus Klaus Klaus Klaus Klaus Klaus"); + cvec_str_emplace_back(vs, "Celine Celine Celine Celine Celine Celine"); + cvec_str_emplace_back(vs, "Kenny Kenny Kenny Kenny Kenny Kenny"); + + cvec_str_emplace_back(vs, "Kelly Kelly Kelly Kelly Kelly Kelly"); + cvec_str_emplace_back(vs, "Jackson Jackson Jackson Jackson Jackson Jackson"); + cvec_str_emplace_back(vs, "Mandy Mandy Mandy Mandy Mandy Mandy"); + cvec_str_emplace_back(vs, "Terry Terry Terry Terry Terry Terry"); + cvec_str_emplace_back(vs, "Sandy Sandy Sandy Sandy Sandy Sandy"); + + cvec_str_emplace_back(vs, "Billy Billy Billy Billy Billy Billy"); + cvec_str_emplace_back(vs, "Cindy Cindy Cindy Cindy Cindy Cindy"); + cvec_str_emplace_back(vs, "Phil Phil Phil Phil Phil Phil"); + cvec_str_emplace_back(vs, "Lindy Lindy Lindy Lindy Lindy Lindy"); + cvec_str_emplace_back(vs, "David David David David David David"); +*/ + size_t num = 0; + c_foreach (i, cvec_str, *vs) + { + cvec_sv_push_back(vsv, csview_from_s(i.ref)); + num += cstr_size(*i.ref); + } + std::cout << "num strings: " << cvec_sv_size(*vsv) << std::endl; + std::cout << "avg str len: " << num / (float)cvec_sv_size(*vsv) << std::endl; +} + +void initMaps(const cvec_str* vs, csmap_str* mapTrans, csmap_ssv* mapSview, + cmap_str* unordmapTrans, cmap_ssv* unordmapSview) +{ + csmap_str_clear(mapTrans); + csmap_ssv_clear(mapSview); + cmap_str_clear(unordmapTrans); + cmap_ssv_clear(unordmapSview); + + size_t n = 0; + c_foreach (i, cvec_str, *vs) + { + csmap_str_insert(mapTrans, cstr_clone(*i.ref), n); + csmap_ssv_insert(mapSview, cstr_clone(*i.ref), n); + cmap_str_insert(unordmapTrans, cstr_clone(*i.ref), n); + cmap_ssv_insert(unordmapSview, cstr_clone(*i.ref), n); + ++n; + } +} + +void benchmark( + const cvec_str* vec_string, + const cvec_sv* vec_stringview, + const csmap_str* mapTrans, + const csmap_ssv* mapSview, + const cmap_str* unordmapTrans, + const cmap_ssv* unordmapSview); + +//const size_t MAX_LOOP = 1000000; +const size_t MAX_LOOP = 2000; + +int main() +{ + c_auto (cvec_str, vec_string) + c_auto (cvec_sv, vec_stringview) + c_auto (csmap_str, mapTrans) + c_auto (csmap_ssv, mapSview) + c_auto (cmap_str, unordmapTrans) + c_auto (cmap_ssv, unordmapSview) + { + std::cout << "Short String Benchmark" << std::endl; + std::cout << "======================" << std::endl; + + initShortStringVec(&vec_string, &vec_stringview); + initMaps(&vec_string, &mapTrans, &mapSview, + &unordmapTrans, &unordmapSview); + + for (int i=0; i<3; ++i) + benchmark( + &vec_string, + &vec_stringview, + &mapTrans, + &mapSview, + &unordmapTrans, + &unordmapSview); + + std::cout << "Long String Benchmark" << std::endl; + std::cout << "=====================" << std::endl; + + initLongStringVec(&vec_string, &vec_stringview); + initMaps(&vec_string, &mapTrans, &mapSview, + &unordmapTrans, &unordmapSview); + for (int i=0; i<3; ++i) + benchmark( + &vec_string, + &vec_stringview, + &mapTrans, + &mapSview, + &unordmapTrans, + &unordmapSview); + } + return 0; +} + +void benchmark( + const cvec_str* vec_string, + const cvec_sv* vec_stringview, + const csmap_str* mapTrans, + const csmap_ssv* mapSview, + const cmap_str* unordmapTrans, + const cmap_ssv* unordmapSview) +{ + size_t grandtotal = 0; + + size_t total = 0; + + timer stopwatch; + total = 0; + stopwatch.start("Trans Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + c_foreach (j, cvec_str, *vec_string) + { + const csmap_str_value* v = csmap_str_get(mapTrans, cstr_str(j.ref)); + if (v) + total += v->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Trans Map with string_view"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + c_foreach (j, cvec_sv, *vec_stringview) + { + const csmap_ssv_value* v = csmap_ssv_get(mapSview, *j.ref); + if (v) + total += v->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Trans Unord Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + c_foreach (j, cvec_str, *vec_string) + { + const cmap_str_value* v = cmap_str_get(unordmapTrans, cstr_str(j.ref)); + if (v) + total += v->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Trans Unord Map with string_view"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + c_foreach (j, cvec_sv, *vec_stringview) + { + const cmap_ssv_value* v = cmap_ssv_get(unordmapSview, *j.ref); + if (v) + total += v->second; + } + } + grandtotal += total; + stopwatch.stop(); + + std::cout << "grandtotal:" << grandtotal << " <--- Ignore this\n" << std::endl; + +} diff --git a/benchmarks/misc/string_bench_STD.cpp b/benchmarks/misc/string_bench_STD.cpp new file mode 100644 index 00000000..595ab632 --- /dev/null +++ b/benchmarks/misc/string_bench_STD.cpp @@ -0,0 +1,370 @@ +// https://www.codeproject.com/Tips/5255442/Cplusplus14-20-Heterogeneous-Lookup-Benchmark +// https://github.com/shaovoon/cpp_hetero_lookup_bench +// Requires c++20, e.g. g++ -std=c++20 + +#include <iostream> +#include <iomanip> +#include <chrono> +#include <string> +#include <string_view> +#include <vector> +#include <map> +#include <unordered_map> +#include <stc/cstr.h> + +std::vector<std::string> read_file(const char* name) +{ + std::vector<std::string> data; + c_auto (cstr, line) + c_autovar (FILE* f = fopen(name, "r"), fclose(f)) + while (cstr_getline(&line, f)) + data.emplace_back(cstr_str(&line)); + return data; +} + +class timer +{ +public: + timer() = default; + void start(const std::string& text_) + { + text = text_; + begin = std::chrono::high_resolution_clock::now(); + } + void stop() + { + auto end = std::chrono::high_resolution_clock::now(); + auto dur = end - begin; + auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count(); + std::cout << std::setw(32) << text << " timing:" << std::setw(5) << ms << "ms" << std::endl; + } + +private: + std::string text; + std::chrono::high_resolution_clock::time_point begin; +}; + +void initShortStringVec(std::vector<std::string>& vs, std::vector<std::string_view>& vsv) +{ + vs.clear(); + vsv.clear(); + + vs = read_file("names.txt"); +/* + vs.push_back("Susan"); + vs.push_back("Jason"); + vs.push_back("Lily"); + vs.push_back("Michael"); + vs.push_back("Mary"); + + vs.push_back("Jerry"); + vs.push_back("Jenny"); + vs.push_back("Klaus"); + vs.push_back("Celine"); + vs.push_back("Kenny"); + + vs.push_back("Kelly"); + vs.push_back("Jackson"); + vs.push_back("Mandy"); + vs.push_back("Terry"); + vs.push_back("Sandy"); + + vs.push_back("Billy"); + vs.push_back("Cindy"); + vs.push_back("Phil"); + vs.push_back("Lindy"); + vs.push_back("David"); +*/ + size_t num = 0; + for (size_t i = 0; i < vs.size(); ++i) + { + vsv.push_back(vs.at(i)); + num += vs.at(i).size(); + } + std::cout << "num strings: " << vsv.size() << std::endl; + std::cout << "avg str len: " << num / (float)vsv.size() << std::endl; +} + +void initLongStringVec(std::vector<std::string>& vs, std::vector<std::string_view>& vsv) +{ + vs.clear(); + vsv.clear(); + + vs = read_file("names.txt"); + for (size_t i = 1; i < vs.size(); ++i) { + vs[i] += vs[i]; + vs[i] += vs[i]; + vs[i] += vs[i]; + } +/* + vs.push_back("Susan Susan Susan Susan Susan Susan"); + vs.push_back("Jason Jason Jason Jason Jason Jason"); + vs.push_back("Lily Lily Lily Lily Lily Lily"); + vs.push_back("Michael Michael Michael Michael Michael Michael"); + vs.push_back("Mary Mary Mary Mary Mary Mary"); + + vs.push_back("Jerry Jerry Jerry Jerry Jerry Jerry"); + vs.push_back("Jenny Jenny Jenny Jenny Jenny Jenny"); + vs.push_back("Klaus Klaus Klaus Klaus Klaus Klaus"); + vs.push_back("Celine Celine Celine Celine Celine Celine"); + vs.push_back("Kenny Kenny Kenny Kenny Kenny Kenny"); + + vs.push_back("Kelly Kelly Kelly Kelly Kelly Kelly"); + vs.push_back("Jackson Jackson Jackson Jackson Jackson Jackson"); + vs.push_back("Mandy Mandy Mandy Mandy Mandy Mandy"); + vs.push_back("Terry Terry Terry Terry Terry Terry"); + vs.push_back("Sandy Sandy Sandy Sandy Sandy Sandy"); + + vs.push_back("Billy Billy Billy Billy Billy Billy"); + vs.push_back("Cindy Cindy Cindy Cindy Cindy Cindy"); + vs.push_back("Phil Phil Phil Phil Phil Phil"); + vs.push_back("Lindy Lindy Lindy Lindy Lindy Lindy"); + vs.push_back("David David David David David David"); +*/ + size_t num = 0; + for (size_t i = 0; i < vs.size(); ++i) + { + vsv.push_back(vs.at(i)); + num += vs.at(i).size(); + } + std::cout << "num strings: " << vsv.size() << std::endl; + std::cout << "avg str len: " << num / (float)vsv.size() << std::endl; +} + +void initMapNormal(const std::vector<std::string>& vs, std::map<std::string, size_t>& mapNormal) +{ + mapNormal.clear(); + for (size_t i = 0; i < vs.size(); ++i) + { + mapNormal.insert(std::make_pair(vs.at(i), i)); + } +} + +void initMapTrans(const std::vector<std::string>& vs, std::map<std::string, size_t, std::less<> >& mapTrans) +{ + mapTrans.clear(); + for (size_t i = 0; i < vs.size(); ++i) + { + mapTrans.insert(std::make_pair(vs.at(i), i)); + } +} + +struct MyEqual : public std::equal_to<> +{ + using is_transparent = void; +}; + +struct string_hash { + using is_transparent = void; + using key_equal = std::equal_to<>; // Pred to use + using hash_type = std::hash<std::string_view>; // just a helper local type + size_t operator()(std::string_view txt) const { return hash_type{}(txt); } + size_t operator()(const std::string& txt) const { return hash_type{}(txt); } + size_t operator()(const char* txt) const { return hash_type{}(txt); } +}; + +void initUnorderedMapNormal(const std::vector<std::string>& vs, std::unordered_map<std::string, size_t>& unordmapNormal) +{ + unordmapNormal.clear(); + for (size_t i = 0; i < vs.size(); ++i) + { + unordmapNormal.insert(std::make_pair(vs.at(i), i)); + } +} + +void initUnorderedMapTrans(const std::vector<std::string>& vs, std::unordered_map<std::string, size_t, string_hash, MyEqual>& unordmapTrans) +{ + unordmapTrans.clear(); + for (size_t i = 0; i < vs.size(); ++i) + { + unordmapTrans.insert(std::make_pair(vs.at(i), i)); + } +} + +void benchmark( + const std::vector<std::string>& vec_shortstr, + const std::vector<std::string_view>& vec_shortstrview, + const std::map<std::string, size_t>& mapNormal, + const std::map<std::string, size_t, std::less<> >& mapTrans, + const std::unordered_map<std::string, size_t>& unordmapNormal, + const std::unordered_map<std::string, size_t, string_hash, MyEqual>& unordmapTrans); + +//const size_t MAX_LOOP = 1000000; +const size_t MAX_LOOP = 2000; + +int main() +{ + std::vector<std::string> vec_shortstr; + std::vector<std::string_view> vec_shortstrview; + + std::map<std::string, size_t> mapNormal; + std::map<std::string, size_t, std::less<> > mapTrans; + initShortStringVec(vec_shortstr, vec_shortstrview); + initMapNormal(vec_shortstr, mapNormal); + initMapTrans(vec_shortstr, mapTrans); + + std::unordered_map<std::string, size_t> unordmapNormal; + std::unordered_map<std::string, size_t, string_hash, MyEqual> unordmapTrans; + initUnorderedMapNormal(vec_shortstr, unordmapNormal); + initUnorderedMapTrans(vec_shortstr, unordmapTrans); + + std::cout << "Short String Benchmark" << std::endl; + std::cout << "======================" << std::endl; + + for (int i=0; i<3; ++i) benchmark( + vec_shortstr, + vec_shortstrview, + mapNormal, + mapTrans, + unordmapNormal, + unordmapTrans); + + std::cout << "Long String Benchmark" << std::endl; + std::cout << "=====================" << std::endl; + + initLongStringVec(vec_shortstr, vec_shortstrview); + initMapNormal(vec_shortstr, mapNormal); + initMapTrans(vec_shortstr, mapTrans); + + initUnorderedMapNormal(vec_shortstr, unordmapNormal); + initUnorderedMapTrans(vec_shortstr, unordmapTrans); + + for (int i=0; i<3; ++i) benchmark( + vec_shortstr, + vec_shortstrview, + mapNormal, + mapTrans, + unordmapNormal, + unordmapTrans); + + return 0; +} + +void benchmark( + const std::vector<std::string>& vec_shortstr, + const std::vector<std::string_view>& vec_shortstrview, + const std::map<std::string, size_t>& mapNormal, + const std::map<std::string, size_t, std::less<> >& mapTrans, + const std::unordered_map<std::string, size_t>& unordmapNormal, + const std::unordered_map<std::string, size_t, string_hash, MyEqual>& unordmapTrans) +{ + size_t grandtotal = 0; + size_t total = 0; + timer stopwatch; +/* + total = 0; + stopwatch.start("Normal Map with string"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = mapNormal.find(vec_shortstr[j]); + if(it!=mapNormal.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Normal Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = mapNormal.find(vec_shortstr[j].c_str()); + if (it != mapNormal.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); +*/ + total = 0; + stopwatch.start("Trans Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = mapTrans.find(vec_shortstr[j].c_str()); + if (it != mapTrans.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Trans Map with string_view"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstrview.size(); ++j) + { + const auto& it = mapTrans.find(vec_shortstrview[j]); + if (it != mapTrans.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); +/* + total = 0; + stopwatch.start("Normal Unord Map with string"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = unordmapNormal.find(vec_shortstr[j]); + if (it != unordmapNormal.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Normal Unord Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = unordmapNormal.find(vec_shortstr[j].c_str()); + if (it != unordmapNormal.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); +*/ + total = 0; + stopwatch.start("Trans Unord Map with char*"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstr.size(); ++j) + { + const auto& it = unordmapTrans.find(vec_shortstr[j].c_str()); + if (it != unordmapTrans.cend()) + total += it->second; + } + } + grandtotal += total; + stopwatch.stop(); + + total = 0; + stopwatch.start("Trans Unord Map with string_view"); + for (size_t i = 0; i < MAX_LOOP; ++i) + { + for (size_t j = 0; j < vec_shortstrview.size(); ++j) + { + const auto& it = unordmapTrans.find(vec_shortstrview[j]); + if (it != unordmapTrans.cend()) + total += it->second; + } + } + grandtotal += total; + + stopwatch.stop(); + + std::cout << "grandtotal:" << grandtotal << " <--- Ignore this\n" << std::endl; + +} |
