Files
mlib/bench/bench-string-2.cpp
T
2020-01-04 15:41:06 +01:00

339 lines
7.8 KiB
C++

/*
* M*LIB - String Bench
*
* Copyright (c) 2017-2020, Patrick Pelissier
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* + Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string>
#include <sstream>
#include <string>
#include <vector>
#include "common.h"
#include "m-string.h"
#ifdef BENCH_CAN_USE_SDS
extern "C" {
#include "sds.h"
};
#endif
#ifdef BENCH_CAN_USE_RAPIDSTRING
#include "rapidstring.h"
#endif
#ifdef BENCH_CAN_USE_BSTRLIB
#include "bstrlib.h"
#include "bstrwrap.h"
#include "bstraux.h"
#endif
/*
* BENCH
* 2000000
* 1. Generate N strings of random numbers 32 bits.
* 2. Concat all strings in a string usigned a random permutation of N.
* 3. Replace "1234" in the string into "WELL" until nothing remains.
* 4. Replace "56789" in the string into "DONE" until nothing remains.
* Return the final string length.
*/
unsigned *permutation_tab = NULL;
void random_permutation(unsigned n)
{
if (permutation_tab) free(permutation_tab);
permutation_tab = (unsigned *) malloc(n * sizeof(unsigned));
if (permutation_tab == NULL) abort();
for(unsigned i = 0; i < n; i++)
permutation_tab[i] = i;
for(unsigned i = 0; i < n; i++) {
unsigned j = rand_get() % n;
unsigned k = rand_get() % n;
unsigned l = permutation_tab[j];
permutation_tab[j] = permutation_tab[k];
permutation_tab[k] = l;
}
}
using namespace std;
size_t bench_stl(unsigned n)
{
vector<string> tab;
tab.resize(n);
for(unsigned i = 0; i < n; i++)
tab[i] = to_string(rand_get());
string str;
for(unsigned i = 0; i < n; i++) {
str += tab[permutation_tab[i]];
}
size_t pos = 0;
do {
pos = str.find("1234", pos);
if (pos != string::npos) {
str.replace (pos, 4, "WELL");
}
} while (pos != string::npos);
pos = 0;
do {
pos = str.find("56789", pos);
if (pos != string::npos) {
str.replace (pos, 5, "DONE");
}
} while (pos != string::npos);
return str.length();
}
size_t bench_mlib(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_printf(tab[i], "%u", rand_get());
}
// P2
string_t str;
string_init(str);
for(unsigned i = 0; i < n; i++) {
string_cat(str, tab[permutation_tab[i]]);
}
// P3
size_t i = 0;
do {
i = string_replace_str(str, "1234", "WELL", i);
} while (i != STRING_FAILURE);
// P4
i = 0;
do {
i = string_replace_str(str, "56789", "DONE", i);
} while (i != STRING_FAILURE);
size_t length = string_size(str);
// Clean
string_clear(str);
for(unsigned i = 0; i < n; i++) {
string_clear(tab[i]);
}
free(tab);
return length;
}
#ifdef BENCH_CAN_USE_BSTRLIB
size_t bench_bstrlib(unsigned n)
{
vector<CBString> tab;
tab.resize(n);
for(unsigned i = 0; i < n; i++) {
char tmp[10];
sprintf(tmp, "%u", rand_get());
tab[i] = tmp;
}
CBString str;
for(unsigned i = 0; i < n; i++) {
str += tab[permutation_tab[i]];
}
size_t pos = 0;
do {
pos = str.find("1234", pos);
if (pos != string::npos) {
str.replace (pos, 4, "WELL");
}
} while (pos != string::npos);
pos = 0;
do {
pos = str.find("56789", pos);
if (pos != string::npos) {
str.replace (pos, 5, "DONE");
}
} while (pos != string::npos);
return str.length();
}
#endif
#ifdef BENCH_CAN_USE_SDS
sds SDS_replace_at(sds str, size_t pos, size_t len, const char str2[])
{
// simple implementation as replace is not available
sds a = sdsnewlen((const void*) str, pos);
a = sdscat(a, str2);
a = sdscat(a, &str[pos+len]);
sdsfree(str);
return a;
}
size_t bench_sds(unsigned n)
{
sds *tab = (sds*) malloc (n * sizeof (sds));
assert (tab != 0);
// P1
for(unsigned i = 0; i < n; i++) {
tab[i] = sdsfromlonglong(rand_get());
}
// P2
sds str = sdsempty();
for(unsigned i = 0; i < n; i++) {
str = sdscat(str, tab[permutation_tab[i]]);
}
// P3
size_t pos = 0;
do {
char *p = strstr(&str[pos], "1234");
pos = p == NULL ? -1U : (p - str);
if (pos != -1U) {
str = SDS_replace_at(str, pos, 4, "WELL");
}
} while (pos != -1U);
// P4
pos = 0;
do {
char *p = strstr(&str[pos], "56789");
pos = p == NULL ? -1U : (p - str);
if (pos != -1U) {
str = SDS_replace_at(str, pos, 5, "DONE");
}
} while (pos != -1U);
size_t length = sdslen(str);
// Clean
sdsfree(str);
for(unsigned i = 0; i < n; i++) {
sdsfree(tab[i]);
}
free(tab);
return length;
}
#endif
#ifdef BENCH_CAN_USE_RAPIDSTRING
void RAPIDSTRING_replace_at(rapidstring *str, size_t pos, size_t len, const char str2[])
{
// simple implementation as replace is not available
rapidstring a;
rs_init_w_n(&a, rs_data(str), pos);
rs_cat(&a, str2);
rs_cat(&a, &rs_data(str)[pos+len] );
rs_free(str);
*str = a;
}
size_t bench_rapidstring(unsigned n)
{
rapidstring *tab = (rapidstring*) malloc (n * sizeof (rapidstring));
assert (tab != 0);
// P1
for(unsigned i = 0; i < n; i++) {
char tmp[10];
sprintf(tmp, "%u", rand_get());
rs_init_w(&tab[i], tmp);
}
// P2
rapidstring str;
rs_init(&str);
for(unsigned i = 0; i < n; i++) {
rs_cat_rs(&str, &tab[permutation_tab[i]]);
}
// P3
size_t pos = 0;
do {
char *p = strstr(&rs_data(&str)[pos], "1234");
pos = p == NULL ? -1U : (p - rs_data(&str));
if (pos != -1U) {
RAPIDSTRING_replace_at(&str, pos, 4, "WELL");
}
} while (pos != -1U);
// P4
pos = 0;
do {
char *p = strstr(&rs_data(&str)[pos], "56789");
pos = p == NULL ? -1U : (p - rs_data(&str));
if (pos != -1U) {
RAPIDSTRING_replace_at(&str, pos, 5, "DONE");
}
} while (pos != -1U);
size_t length = rs_len(&str);
// Clean
rs_free(&str);
for(unsigned i = 0; i < n; i++) {
rs_free(&tab[i]);
}
free(tab);
return length;
}
#endif
int main(int argc, const char *argv[])
{
unsigned length, n = atoi(argv[1]);
unsigned select = atoi(argv[2]);
const char *name;
random_permutation(n);
rand_init();
unsigned long long t0 = cputime();
switch (select) {
case 0:
length = bench_mlib(n);
name = "MLIB";
break;
case 1:
length = bench_stl(n);
name = "STL";
break;
#ifdef BENCH_CAN_USE_SDS
case 2:
length = bench_sds(n);
name = "SDS";
break;
#endif
#ifdef BENCH_CAN_USE_RAPIDSTRING
case 3:
length = bench_rapidstring(n);
name = "RAPID";
break;
#endif
#ifdef BENCH_CAN_USE_BSTRLIB
case 4:
length = bench_bstrlib(n);
name = "BSTRLIB";
break;
#endif
default:
exit(0);
}
unsigned long long t1 = cputime();
printf("%5.5s LENGTH=%u T= %f s\n", name, length, (t1-t0) / 1000000.0 );
return 0;
}