diff --git a/bench/Makefile b/bench/Makefile index 15d47398..27e92985 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -430,6 +430,9 @@ bench-string-step4: @if test -n "$${GLIB}" ; then $(MAKE) bench-string-step5 BENCH_DEF="$(BENCH_DEF) -DBENCH_CAN_USE_GLIB $$(pkg-config --cflags --libs glib-2.0)" ; else $(MAKE) bench-string-step5 BENCH_DEF="$(BENCH_DEF)"; fi bench-string-step5: + @if test -n "$${POTTERY}" ; then $(MAKE) bench-string-step6 BENCH_DEF="$(BENCH_DEF) -DBENCH_CAN_USE_POTTERY -I$${POTTERY}/include -I$${POTTERY}/util/ $${POTTERY}/util/pottery/string/string.c" ; else $(MAKE) bench-string-step6 BENCH_DEF="$(BENCH_DEF)"; fi + +bench-string-step6: $(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -DBENCH_CAN_USE_STL -DBENCH_CAN_USE_MSTARLIB bench-string.cpp common.c $(BENCH_DEF) -o bench-string.exe $(CXX) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -DBENCH_CAN_USE_STL -DBENCH_CAN_USE_MSTARLIB bench-string-2.cpp common.c $(BENCH_DEF) -o bench-string-2.exe @./bench-string.exe @@ -437,6 +440,7 @@ bench-string-step5: @./bench-string-2.exe 2000000 1 @./bench-string-2.exe 2000000 2 @./bench-string-2.exe 2000000 4 + @./bench-string-2.exe 2000000 5 bench-string-pgo: $(MAKE) bench-string XCFLAGS="-fprofile-generate=pgo" diff --git a/bench/bench-string-2.cpp b/bench/bench-string-2.cpp index e776eee2..efb3f291 100644 --- a/bench/bench-string-2.cpp +++ b/bench/bench-string-2.cpp @@ -27,6 +27,7 @@ #include #include +#define M_USE_SMALL_NAME 0 #include "common.h" #include "m-string.h" @@ -43,6 +44,10 @@ extern "C" { #include "bstraux.h" #endif +#if defined(BENCH_CAN_USE_POTTERY) +#include "pottery/string/string.h" +#endif + /* * BENCH * 2000000 @@ -104,27 +109,28 @@ size_t bench_stl(unsigned n) size_t bench_mlib(unsigned n) { - string_t *tab = (string_t*) malloc (n * sizeof (string_t)); + m_string_t *tab = (m_string_t*) malloc (n * sizeof (m_string_t)); assert (tab != 0); // P1 for(unsigned i = 0; i < n; i++) { - string_init(tab[i]); - string_printf(tab[i], "%u", rand_get()); + m_string_init(tab[i]); + m_string_printf(tab[i], "%u", rand_get()); } // P2 - string_t str; - string_init(str); + m_string_t str; + m_string_init(str); for(unsigned i = 0; i < n; i++) { - string_cat(str, tab[permutation_tab[i]]); + m_string_cat(str, tab[permutation_tab[i]]); } // P3 - string_replace_all_str(str, "1234", "WELL"); - string_replace_all_str(str, "56789", "DONE"); - size_t length = string_size(str); + m_string_replace_all_str(str, "1234", "WELL"); + m_string_replace_all_str(str, "56789", "DONE"); + size_t length = m_string_size(str); + // Clean - string_clear(str); + m_string_clear(str); for(unsigned i = 0; i < n; i++) { - string_clear(tab[i]); + m_string_clear(tab[i]); } free(tab); return length; @@ -217,6 +223,57 @@ size_t bench_sds(unsigned n) } #endif +#if defined(BENCH_CAN_USE_POTTERY) + +size_t pottery_find_cstr(string_t *b, size_t index, const char *pattern) +{ + // I cannot find such function in the API + const char *s = string_cstr(b); + const char *r = strstr(&s[index], pattern); + return r == NULL ? SIZE_MAX : r - s; +} + +void pottery_replace_all_str(string_t *str, const char *s, const char *d) +{ + size_t i = 0; + while (true) { + i = pottery_find_cstr(str, i, s); + if (i==SIZE_MAX) return; + string_remove(str, i, strlen(s)); + string_insert_cstr(str, i, d); + } +} + +size_t bench_pottery(unsigned n) +{ + string_t *tab = (string_t*) malloc (n * sizeof (string_t)); + assert (tab != 0); + // P1 + for(unsigned i = 0; i < n; i++) { + string_init(&tab[i]); + string_append_format(&tab[i], "%u", rand_get()); + } + // P2 + string_t str; + string_init(&str); + for(unsigned i = 0; i < n; i++) { + string_append_string(&str, &tab[permutation_tab[i]]); + } + // P3 + + pottery_replace_all_str(&str, "1234", "WELL"); + pottery_replace_all_str(&str, "56789", "DONE"); + size_t length = string_length(&str); + + // Clean + string_clear(&str); + for(unsigned i = 0; i < n; i++) { + string_clear(&tab[i]); + } + free(tab); + return length; +} +#endif int main(int argc, const char *argv[]) { @@ -247,6 +304,12 @@ int main(int argc, const char *argv[]) length = bench_bstrlib(n); name = "BSTRLIB"; break; +#endif +#if defined(BENCH_CAN_USE_POTTERY) + case 5: + length = bench_pottery(n); + name = "POTTERY"; + break; #endif default: exit(0); diff --git a/bench/bench-string.cpp b/bench/bench-string.cpp index dca71d01..555b77ff 100644 --- a/bench/bench-string.cpp +++ b/bench/bench-string.cpp @@ -35,7 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Update of integrating M*LIB, LIBSRT, SDS & GLIB +/* Update of integrating M*LIB, LIBSRT, SDS, GLIB & POTTERY Copyright (c) 2018-2022 Patrick Pelissier */ @@ -53,6 +53,7 @@ #include #define NDEBUG +#define M_USE_SMALL_NAME 0 #include "common.h" #ifdef BENCH_CAN_USE_MSTARLIB @@ -83,6 +84,10 @@ extern "C" { #include "gmodule.h" #endif +#if defined(BENCH_CAN_USE_POTTERY) +#include "pottery/string/string.h" +#endif + /* Time of a test */ #define TEST_SECONDS (5) @@ -433,11 +438,11 @@ int testSRT_concat (int count) { int testMLIB_emptyCtor (int count) { int i, c = 0; for (c=i=0; i < count; i++) { - string_t b; - string_init(b); + m_string_t b; + m_string_init(b); BARRIER(&b); - c += string_size(b) ^i; - string_clear(b); + c += m_string_size(b) ^i; + m_string_clear(b); } return c; } @@ -445,11 +450,11 @@ int testMLIB_emptyCtor (int count) { int testMLIB_nonemptyCtor (int count) { int i, c = 0; for (c=i=0; i < count; i++) { - string_t b; - string_init_set_str(b, TESTSTRING1); + m_string_t b; + m_string_init_set_str(b, TESTSTRING1); BARRIER(&b); - c += string_size(b) ^i; - string_clear(b); + c += m_string_size(b) ^i; + m_string_clear(b); } return c; } @@ -457,93 +462,93 @@ int testMLIB_nonemptyCtor (int count) { int testMLIB_smallnonemptyCtor (int count) { int i, c = 0; for (c=i=0; i < count; i++) { - string_t b; - string_init_set_str(b, SMALLTESTSTRING1); + m_string_t b; + m_string_init_set_str(b, SMALLTESTSTRING1); BARRIER(&b); - c += string_size(b) ^i; - string_clear(b); + c += m_string_size(b) ^i; + m_string_clear(b); } return c; } int testMLIB_cstrAssignment (int count) { int i, c = 0; - string_t b; - string_init(b); + m_string_t b; + m_string_init(b); for (c=i=0; i < count; i++) { - string_set_str(b, TESTSTRING1); + m_string_set_str(b, TESTSTRING1); BARRIER(&b); - c += string_size(b) ^i; + c += m_string_size(b) ^i; } - string_clear(b); + m_string_clear(b); return c; } int testMLIB_extraction (int count) { int i, c = 0; - string_t b; - string_init_set_str(b, TESTSTRING1); + m_string_t b; + m_string_init_set_str(b, TESTSTRING1); for (c=i=0; i < count; i++) { - c += string_get_char(b, (i & 7)); - c += string_get_char(b, (i & 7) ^ 8); - c += string_get_char(b, (i & 7) ^ 4) ^i; + c += m_string_get_char(b, (i & 7)); + c += m_string_get_char(b, (i & 7) ^ 8); + c += m_string_get_char(b, (i & 7) ^ 4) ^i; BARRIER(&b); } - string_clear(b); + m_string_clear(b); return c; } int testMLIB_scan (int count) { int i, c = 0; - string_t b; - string_init_set_str(b, "Dot. 123. Some more data."); + m_string_t b; + m_string_init_set_str(b, "Dot. 123. Some more data."); for (c=i=0; i < count; i++) { - c += string_search_char (b, '.'); - c += string_search_str (b, "123"); - c += string_search_pbrk (b, "sm") ^i; + c += m_string_search_char (b, '.'); + c += m_string_search_str (b, "123"); + c += m_string_search_pbrk (b, "sm") ^i; BARRIER(&b); } - string_clear(b); + m_string_clear(b); return c; } int testMLIB_concat (int count) { int i, j, c = 0; - string_t a, accum; - string_init_set_str(a, TESTSTRING1); - string_init (accum); + m_string_t a, accum; + m_string_init_set_str(a, TESTSTRING1); + m_string_init (accum); for (j=0; j < count; j++) { - string_set_str(accum, ""); + m_string_set_str(accum, ""); for (i=0; i < 250; i++) { - string_cat(accum, a); - string_cat_str(accum, "!!"); + m_string_cat(accum, a); + m_string_cat_str(accum, "!!"); BARRIER(&accum); - c += string_size(accum) ^i; + c += m_string_size(accum) ^i; } } - string_clear(a); - string_clear(accum); + m_string_clear(a); + m_string_clear(accum); return c; } int testMLIB_replace (int count) { int j, c = 0; - string_t a; - string_init_set_str(a, TESTSTRING1); + m_string_t a; + m_string_init_set_str(a, TESTSTRING1); for (j=0; j < count; j++) { - string_replace_at(a, 11, 4, "XXXXXX"); - string_replace_at(a, 23, 2, "XXXXXX"); - string_replace_at(a, 4, 8, "XX"); + m_string_replace_at(a, 11, 4, "XXXXXX"); + m_string_replace_at(a, 23, 2, "XXXXXX"); + m_string_replace_at(a, 4, 8, "XX"); BARRIER(&a); - c += string_size(a) ^j; + c += m_string_size(a) ^j; } - string_clear(a); + m_string_clear(a); return c; } #endif @@ -774,6 +779,118 @@ int testGLIB_concat (int count) { //int testGLIB_replace (int count): not available #endif +#ifdef BENCH_CAN_USE_POTTERY +int testPOTTERY_emptyCtor (int count) { + int i, c = 0; + for (c=i=0; i < count; i++) { + string_t b; + string_init(&b); + BARRIER(&b); + c += string_length(&b) ^i; + string_clear(&b); + } + return c; +} + +int testPOTTERY_nonemptyCtor (int count) { + int i, c = 0; + for (c=i=0; i < count; i++) { + string_t b; + string_init_cstr(&b, TESTSTRING1); + BARRIER(&b); + c += string_length(&b) ^i; + string_clear(&b); + } + return c; +} + +int testPOTTERY_smallnonemptyCtor (int count) { + int i, c = 0; + for (c=i=0; i < count; i++) { + string_t b; + string_init_cstr(&b, SMALLTESTSTRING1); + BARRIER(&b); + c += string_length(&b) ^i; + string_clear(&b); + } + return c; +} + +int testPOTTERY_cstrAssignment (int count) { + int i, c = 0; + string_t b; + string_init(&b); + for (c=i=0; i < count; i++) { + string_set_cstr(&b, TESTSTRING1); + BARRIER(&b); + c += string_length(&b) ^i; + } + string_clear(&b); + return c; +} + +int testPOTTERY_extraction (int count) { + int i, c = 0; + + string_t b; + string_init_cstr(&b, TESTSTRING1); + + for (c=i=0; i < count; i++) { + c += string_cstr(&b)[(i & 7)]; + c += string_cstr(&b)[(i & 7) ^ 8]; + c += string_cstr(&b)[(i & 7) ^ 4] ^i; + BARRIER(&b); + } + string_clear(&b); + return c; +} + +size_t pottery_find_cstr(string_t *b, const char *pattern) +{ + // I cannot find such function in the API + const char *s = string_cstr(b); + const char *r = strstr(s, pattern); + return r == NULL ? SIZE_MAX : r - s; +} + +int testPOTTERY_scan (int count) { + int i, c = 0; + string_t b; + string_init_cstr(&b, "Dot. 123. Some more data."); + + for (c=i=0; i < count; i++) { + c += string_find_char (&b, 0, '.'); + c += pottery_find_cstr (&b, "123"); + c += string_find_chars_cstr (&b, 0, "sm") ^i; + BARRIER(&b); + } + string_clear(&b); + return c; +} + +int testPOTTERY_concat (int count) { + int i, j, c = 0; + string_t a, accum; + string_init_cstr(&a, TESTSTRING1); + string_init (&accum); + + for (j=0; j < count; j++) { + string_set_cstr(&accum, ""); + for (i=0; i < 250; i++) { + string_append_string(&accum, &a); + string_append_cstr(&accum, "!!"); + BARRIER(&accum); + c += string_length(&accum) ^i; + } + } + string_clear(&a); + string_clear(&accum); + return c; +} + +// No replace function available +#endif + #define NTESTS 8 struct flags { @@ -999,6 +1116,37 @@ int benchTest (const struct flags * runflags) { } #endif +#ifdef BENCH_CAN_USE_POTTERY + if (runflags->runtest[0]) { + c += timeTest (cps, testPOTTERY_emptyCtor, 100000); + print ("POTTERY", "empty constructor", cps); + } + if (runflags->runtest[1]) { + c += timeTest (cps, testPOTTERY_nonemptyCtor, 100000); + print ("POTTERY", "non-empty constructor", cps); + } + if (runflags->runtest[2]) { + c += timeTest (cps, testPOTTERY_smallnonemptyCtor, 100000); + print ("POTTERY", "small non-empty constructor", cps); + } + if (runflags->runtest[3]) { + c += timeTest (cps, testPOTTERY_cstrAssignment, 100000); + print ("POTTERY", "Char * assignment", cps); + } + if (runflags->runtest[4]) { + c += timeTest (cps, testPOTTERY_extraction, 100000); + print ("POTTERY", "char extraction", cps); + } + if (runflags->runtest[5]) { + c += timeTest (cps, testPOTTERY_scan, 100000); + print ("POTTERY", "scan", cps); + } + if (runflags->runtest[6]) { + c += timeTest (cps, testPOTTERY_concat, 10); + print ("POTTERY", "concatenation", cps * 250); + } +#endif + return c; }