summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2022-03-29 09:03:27 +0200
committerTyge Løvset <[email protected]>2022-03-29 09:03:27 +0200
commite507d0a01fb2210913c3b546817c04c58f931b9e (patch)
treecf05f18312e2b4262bed73fc361e6dc9d902a613
parent3a291671c2583033f821b7c8d68d22b1897a6e15 (diff)
downloadSTC-modified-e507d0a01fb2210913c3b546817c04c58f931b9e.tar.gz
STC-modified-e507d0a01fb2210913c3b546817c04c58f931b9e.zip
Added some sso benchmarks and a minor tweak.
-rw-r--r--benchmarks/misc/sso_bench.c52
-rw-r--r--benchmarks/misc/sso_bench2.cpp85
-rw-r--r--include/stc/alt/cstr.h8
-rw-r--r--include/stc/forward.h2
4 files changed, 142 insertions, 5 deletions
diff --git a/benchmarks/misc/sso_bench.c b/benchmarks/misc/sso_bench.c
new file mode 100644
index 00000000..0d40a017
--- /dev/null
+++ b/benchmarks/misc/sso_bench.c
@@ -0,0 +1,52 @@
+// 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 = stc64_random() % max;
+ static char chr[64] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
+ c_forrange (i, n)
+ buf[i] = chr[stc64_random() & 63];
+ buf[n] = '\0';
+}
+
+enum {N = 10000000};
+
+int main(void) {
+
+ c_auto (Vec, vec)
+ c_auto (Map, map) {
+ char buf[128];
+
+ stc64_srandom(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_bench2.cpp
new file mode 100644
index 00000000..4ef03d3c
--- /dev/null
+++ b/benchmarks/misc/sso_bench2.cpp
@@ -0,0 +1,85 @@
+#include <string>
+#include <iostream>
+#include <vector>
+#include <chrono>
+#include <stc/alt/cstr.h>
+#define i_val_str
+#include <stc/cstack.h>
+
+#define ROTL_(x, k) (x << (k) | x >> (8*sizeof(x) - (k)))
+
+static uint64_t g_romutrio[3] = {
+ 0x26aa069ea2fb1a4dULL, 0x70c72c95cd592d04ULL,
+ 0x504f333d3aa0b359ULL,
+};
+
+static inline uint64_t romutrio(void) {
+ uint64_t *s = g_romutrio, xp = s[0], yp = s[1], zp = s[2];
+ s[0] = 15241094284759029579u * zp;
+ s[1] = yp - xp; s[1] = ROTL_(s[1], 12);
+ s[2] = zp - yp; s[2] = ROTL_(s[2], 44);
+ return xp;
+}
+
+static const char CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=+";
+static const int ARRAY_SIZE = sizeof(CHARS) - 1;
+
+static const int BENCHMARK_SIZE = 10000000;
+static const int MAX_STRING_LENGTH = 20;
+
+using time_point = std::chrono::high_resolution_clock::time_point;
+
+void addRandomString_STD(std::vector<std::string>& vec, const int length) {
+ std::string s(length, 0);
+ char* p = s.data();
+ for (int i = 0; i < length; ++i) {
+ p[i] = CHARS[romutrio() & 63];
+ }
+ s.append(s);
+ vec.push_back(s);
+}
+
+void addRandomString_STC(cstack_str& vec, const int length) {
+ cstr s = cstr_with_size(length, 0);
+ char* p = cstr_data(&s);
+ for (int i = 0; i < length; ++i) {
+ p[i] = CHARS[romutrio() & 63];
+ }
+ cstr_append_s(&s, s);
+ cstack_str_push(&vec, s);
+}
+
+template <class L, typename R>
+void benchmark(L& vec, const int length, R addRandomString) {
+ time_point t1 = std::chrono::high_resolution_clock::now();
+
+ for (int i = 0; i < BENCHMARK_SIZE; i++) {
+ addRandomString(vec, length);
+ }
+
+ time_point t2 = std::chrono::high_resolution_clock::now();
+ const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
+ std::cerr << length*2 << "\t" << duration;
+}
+
+
+int main() {
+ 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);
+ benchmark(vec, length, addRandomString_STD);
+ std::cout << '\t' << vec[0] << '\n';
+ }
+ std::cerr << "\nlength\ttime\tSTC string\n";
+ for (int length = 1; length <= MAX_STRING_LENGTH; length++) {
+ cstack_str vec = cstack_str_with_capacity(BENCHMARK_SIZE);
+ benchmark(vec, length, addRandomString_STC);
+ std::cout << '\t' << cstr_str(&vec.data[0]) << '\n';
+ cstack_str_drop(&vec);
+ }
+
+ std::cerr << "size std::string : " << sizeof(std::string) << std::endl
+ << "size STC string : " << sizeof(cstr) << std::endl;
+ return 0;
+}
diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h
index 211e169a..875d47d5 100644
--- a/include/stc/alt/cstr.h
+++ b/include/stc/alt/cstr.h
@@ -39,12 +39,12 @@
/**************************** PRIVATE API **********************************/
enum { SSO_CAP = sizeof(_cstr_rep_t) - 1 };
-#define cstr_is_long(s) (bool)((s)->sso.cap_len & 128)
+#define cstr_is_long(s) ((s)->sso.last > 127)
#define cstr_select_(s, memb) (cstr_is_long(s) ? cstr_l_##memb : cstr_s_##memb)
#define cstr_s_cap(s) SSO_CAP
-#define cstr_s_size(s) ((size_t)(SSO_CAP - (s)->sso.cap_len))
-#define cstr_s_set_size(s, len) ((s)->sso.cap_len = SSO_CAP - (len), (s)->sso.data[len] = 0)
+#define cstr_s_size(s) ((size_t)(SSO_CAP - (s)->sso.last))
+#define cstr_s_set_size(s, len) ((s)->sso.last = SSO_CAP - (len), (s)->sso.data[len] = 0)
#define cstr_s_data(s) (s)->sso.data
#define cstr_s_end(s) ((s)->sso.data + cstr_s_size(s))
@@ -79,7 +79,7 @@ STC_INLINE _cstr_rep_t cstr_rep_(cstr* self) {
#define cstr_new(literal) cstr_from_n(literal, c_strlen_lit(literal))
#define cstr_npos (SIZE_MAX >> 1)
-#define cstr_null (c_make(cstr){.sso = {.cap_len = SSO_CAP}})
+#define cstr_null (c_make(cstr){.sso = {.last = SSO_CAP}})
#define cstr_toraw(self) cstr_str(self)
STC_API char* cstr_reserve(cstr* self, size_t cap);
diff --git a/include/stc/forward.h b/include/stc/forward.h
index ea552204..026834d0 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -45,7 +45,7 @@
#ifdef CSTR_IS_SSO
typedef struct { char* data; size_t size, cap; } _cstr_rep_t;
typedef union {
- struct { char data[sizeof(_cstr_rep_t) - 1], cap_len; } sso;
+ struct { char data[sizeof(_cstr_rep_t) - 1]; uint8_t last; } sso;
struct { char* data; size_t size, ncap; } lon;
} cstr;
#else