diff --git a/CMakeLists.txt b/CMakeLists.txt index dba4891baf0c7107caa00d8f11a39903c237182d..208fd30e91b23b41b61593eb0541464bd15d6c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ if (BUILD_DAP_SDK_TESTS) # set(DAPSDK_MODULES ${DAPSDK_MODULES} global-db) set(SPHINCSPLUS_FLEX ON) message("[+] Enable dap_sdk_tests") + add_definitions("-DDAP_SDK_TESTS") endif () if (DAPSDK_MODULES MATCHES "test-framework") diff --git a/global-db/dap_global_db_driver_sqlite.c b/global-db/dap_global_db_driver_sqlite.c index 251ce99dd51988a3899b955f5b61ca19a147d62c..fec594c19b8d6da8b343d1878ba1669dafac9385 100644 --- a/global-db/dap_global_db_driver_sqlite.c +++ b/global-db/dap_global_db_driver_sqlite.c @@ -487,7 +487,7 @@ static dap_global_db_pkt_pack_t *s_db_sqlite_get_by_hash(const char *a_group, da char *l_str_query_count = sqlite3_mprintf("SELECT COUNT(*) FROM '%s' " " WHERE driver_key IN (%s)", l_table_name, l_blob_str); - char *l_str_query_size = sqlite3_mprintf("SELECT SUM(LENGTH(key)) + SUM(LENGTH(value)) + SUM(LENGTH(sign)) FROM '%s' " + char *l_str_query_size = sqlite3_mprintf("SELECT COALESCE(SUM(LENGTH(key)), 0) + COALESCE(SUM(LENGTH(value)), 0) + COALESCE(SUM(LENGTH(sign)), 0) FROM '%s' " " WHERE driver_key IN (%s)", l_table_name, l_blob_str); char *l_str_query = sqlite3_mprintf("SELECT * FROM '%s'" diff --git a/global-db/include/dap_global_db_driver.h b/global-db/include/dap_global_db_driver.h index 811ead5eaf8569474afb18bac821b4eb52c4a6a7..2eb180af24fc9c279bc8dc1f78a496d9da0c5e88 100644 --- a/global-db/include/dap_global_db_driver.h +++ b/global-db/include/dap_global_db_driver.h @@ -39,8 +39,13 @@ #define DAP_GLOBAL_DB_GROUPS_COUNT_MAX 1024UL /* A maximum number of groups */ #define DAP_GLOBAL_DB_KEY_SIZE_MAX 512UL /* A limit for the key's length in DB */ -#define DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT 256UL /* Default count of records to return with conditional read */ -#define DAP_GLOBAL_DB_COND_READ_KEYS_DEFAULT 512UL /* Default count of keys to return with conditional read */ +#ifndef DAP_SDK_TESTS + #define DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT 256UL /* Default count of records to return with conditional read */ + #define DAP_GLOBAL_DB_COND_READ_KEYS_DEFAULT 512UL /* Default count of keys to return with conditional read */ +#else // to more fast tests + #define DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT 25UL + #define DAP_GLOBAL_DB_COND_READ_KEYS_DEFAULT 50UL +#endif // Main record flags (DB saved) #define DAP_GLOBAL_DB_RECORD_DEL BIT(0) /* Information of record deletion (key, timestamp and sign) propagated over sync */ diff --git a/global-db/test/dap_global_db_test.c b/global-db/test/dap_global_db_test.c index 03cf15e9c3cffc9c5ada32f92b2dcbc1c3d849bf..73865edb32f4826959ca50316bf4514c80e136b7 100644 --- a/global-db/test/dap_global_db_test.c +++ b/global-db/test/dap_global_db_test.c @@ -36,18 +36,34 @@ static const char *s_db_types[] = { }; // benchmarks -static int s_write = 0; -static int s_read = 0; -static int s_read_cond_store = 0; -static int s_count = 0; -static int s_tx_start_end = 0; -static int s_flush = 0; -static int s_is_obj = 0; -static int s_is_hash = 0; -static int s_last = 0; -static int s_read_hashes = 0; -static int s_get_by_hash = 0; -static int s_get_groups_by_mask = 0; +static uint64_t s_write = 0; +static uint64_t s_rewrite = 0; +static uint64_t s_read = 0; +static uint64_t s_read_all_with_holes = 0; +static uint64_t s_read_all_without_holes = 0; +static uint64_t s_read_cond_store = 0; +static uint64_t s_count_with_holes = 0; +static uint64_t s_count_without_holes = 0; +static uint64_t s_tx_start_end_erase = 0; +static uint64_t s_tx_start_end_add = 0; +static uint64_t s_flush = 0; +static uint64_t s_is_obj = 0; +static uint64_t s_is_obj_wrong = 0; +static uint64_t s_is_obj_not_existed = 0; +static uint64_t s_is_hash = 0; +static uint64_t s_is_hash_wrong = 0; +static uint64_t s_is_hash_not_existed = 0; +static uint64_t s_last_with_holes = 0; +static uint64_t s_last_without_holes = 0; +static uint64_t s_last_with_holes_wrong = 0; +static uint64_t s_last_without_holes_wrong = 0; +static uint64_t s_last_with_holes_not_existed = 0; +static uint64_t s_last_without_holes_not_existed = 0; +static uint64_t s_read_hashes = 0; +static uint64_t s_read_hashes_wrong = 0; +static uint64_t s_read_hashes_not_existed = 0; +static uint64_t s_get_by_hash = 0; +static uint64_t s_get_groups_by_mask = 0; typedef struct __dap_test_record__ { @@ -83,7 +99,7 @@ static int s_test_create_db(const char *db_type) return rc; } -static int s_test_write(size_t a_count) +static int s_test_write(size_t a_count, bool a_with_value) { dap_store_obj_t l_store_obj = {0}; int l_value_len = 0, *l_pvalue, i, ret; @@ -99,9 +115,8 @@ static int s_test_write(size_t a_count) /* "Table" name */ l_store_obj.key = l_key; /* Point <.key> to the buffer with the key of record */ - l_store_obj.value = (uint8_t *) l_value; /* Point <.value> to static buffer area */ + l_store_obj.value = a_with_value ? (uint8_t *) l_value : NULL; /* Point <.value> to static buffer area */ prec = (dap_db_test_record_t *) l_value; - int l_time = 0; size_t l_rewrite_count = rand() % (a_count / 2) + 2; for (size_t i = 0; i < a_count; ++i) { @@ -112,17 +127,17 @@ static int s_test_write(size_t a_count) clock_gettime(CLOCK_REALTIME, &now); /* Get and save record's timestamp */ l_store_obj.timestamp = ((uint64_t)now.tv_sec << 32) | ((uint32_t) (now.tv_nsec)); - - prec->len = rand() % DAP_DB$SZ_DATA + 1; /* Variable payload length */ - l_pvalue = (int *) prec->data; - for (int i = prec->len / sizeof(int); i--; l_pvalue++) /* Fill record's payload with random data */ - *l_pvalue = rand() + 1; - sprintf(prec->data, "DATA$%08zx%s", i, i < l_rewrite_count ? "rw" : ""); /* Just for fun ... */ - l_value_len = prec->len + sizeof(dap_db_test_record_t); - l_store_obj.value_len = l_value_len; - assert(l_store_obj.value_len < sizeof(l_value)); - - dap_hash_fast (prec->data, prec->len, &prec->csum); /* Compute a hash of the payload part of the record */ + if (a_with_value) { + prec->len = rand() % DAP_DB$SZ_DATA + 1; /* Variable payload length */ + l_pvalue = (int *) prec->data; + for (int i = prec->len / sizeof(int); i--; l_pvalue++) /* Fill record's payload with random data */ + *l_pvalue = rand() + 1; + sprintf(prec->data, "DATA$%08zx%s", i, i < l_rewrite_count ? "rw" : ""); /* Just for fun ... */ + l_value_len = prec->len + sizeof(dap_db_test_record_t); + l_store_obj.value_len = l_value_len; + assert(l_store_obj.value_len < sizeof(l_value)); + dap_hash_fast (prec->data, prec->len, &prec->csum); /* Compute a hash of the payload part of the record */ + } if (i >= l_rewrite_count) { l_store_obj.flags = i % DAP_DB$SZ_HOLES ? 0 : DAP_GLOBAL_DB_RECORD_DEL; @@ -130,9 +145,9 @@ static int s_test_write(size_t a_count) l_store_obj.sign = dap_store_obj_sign(&l_store_obj, l_enc_key, &l_store_obj.crc); log_it(L_DEBUG, "Store object: [%s, %s, %zu octets]", l_store_obj.group, l_store_obj.key, l_store_obj.value_len); - l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); ret = dap_global_db_driver_add(&l_store_obj, 1); - s_write += get_cur_time_msec() - l_time; + s_write += get_cur_time_nsec() - l_time; dap_assert_PIF(!ret, "Write record to DB"); // rewrite block @@ -145,9 +160,9 @@ static int s_test_write(size_t a_count) l_store_obj.flags = i % DAP_DB$SZ_HOLES ? 0 : DAP_GLOBAL_DB_RECORD_DEL; l_store_obj.sign = dap_store_obj_sign(&l_store_obj, l_enc_key, &l_store_obj.crc); - l_time = get_cur_time_msec(); + l_time = get_cur_time_nsec(); ret = dap_global_db_driver_add(&l_store_obj, 1); - s_write += get_cur_time_msec() - l_time; + s_rewrite += get_cur_time_nsec() - l_time; dap_assert_PIF(!ret, "Rewrite with key conflict record to DB"); } @@ -155,9 +170,7 @@ static int s_test_write(size_t a_count) l_store_obj.crc = i + 1; snprintf(l_key, sizeof(l_key), "KEY$%09zx", i); - l_time = get_cur_time_msec(); ret = dap_global_db_driver_add(&l_store_obj, 1); - s_write += get_cur_time_msec() - l_time; dap_assert_PIF(!ret, "Write record to wrong group DB"); DAP_DEL_Z(l_store_obj.sign); } @@ -166,19 +179,18 @@ static int s_test_write(size_t a_count) return 0; } -static int s_test_read(size_t a_count) +static int s_test_read(size_t a_count, bool a_bench) { dap_test_msg("Start reading %zu records ...", a_count); - int l_time = 0; for (size_t i = 0; i < a_count; ++i ) { dap_chain_hash_fast_t csum = { 0 };; dap_db_test_record_t *prec = NULL; char l_key[64] = { 0 }; snprintf(l_key, sizeof(l_key), "KEY$%08zx", i); /* Generate a key of record */ - l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); dap_store_obj_t *l_store_obj = dap_global_db_driver_read(DAP_DB$T_GROUP, l_key, NULL, true); - s_read += get_cur_time_msec() - l_time; + s_read += a_bench ? get_cur_time_nsec() - l_time : 0; dap_assert_PIF(l_store_obj, "Record-Not-Found"); if (l_store_obj->sign) // to test rewriting with hash conflict some records wiwthout sign @@ -186,14 +198,16 @@ static int s_test_read(size_t a_count) dap_assert_PIF(!strcmp(DAP_DB$T_GROUP, l_store_obj->group), "Check group name"); dap_assert_PIF(!strcmp(l_key, l_store_obj->key), "Check key name"); - prec = (dap_db_test_record_t *) l_store_obj->value; - log_it(L_DEBUG, "Retrieved object: [%s, %s, %zu octets]", l_store_obj->group, l_store_obj->key, - l_store_obj->value_len); - log_it(L_DEBUG, "Record: ['%.*s', %d octets]", prec->len, prec->data, prec->len); - dap_hash_fast(prec->data, prec->len, - &csum); /* Compute a hash of the payload part of the record */ - dap_assert_PIF(memcmp(&csum, &prec->csum, sizeof(dap_chain_hash_fast_t)) == 0, - "Record check sum"); /* Integriry checking ... */ + if (l_store_obj->value) { + prec = (dap_db_test_record_t *) l_store_obj->value; + log_it(L_DEBUG, "Retrieved object: [%s, %s, %zu octets]", l_store_obj->group, l_store_obj->key, + l_store_obj->value_len); + log_it(L_DEBUG, "Record: ['%.*s', %d octets]", prec->len, prec->data, prec->len); + dap_hash_fast(prec->data, prec->len, + &csum); /* Compute a hash of the payload part of the record */ + dap_assert_PIF(memcmp(&csum, &prec->csum, sizeof(dap_chain_hash_fast_t)) == 0, + "Record check sum"); /* Integriry checking ... */ + } dap_store_obj_free_one(l_store_obj); } dap_pass_msg("read check"); @@ -201,16 +215,87 @@ static int s_test_read(size_t a_count) return 0; } +static int s_test_read_all(size_t a_count) +{ + dap_test_msg("Start reading all %zu records ...", a_count); + // with holes + size_t l_count = 0; + s_read_all_with_holes = get_cur_time_nsec(); + dap_store_obj_t *l_store_obj_all = dap_global_db_driver_read(DAP_DB$T_GROUP, NULL, &l_count, true); + s_read_all_with_holes = get_cur_time_nsec() - s_read_all_with_holes; + dap_assert_PIF(l_count == a_count, "Count of all read records with holes not equal count of write records"); + for (size_t i = 0; i < l_count; ++i ) { + dap_store_obj_t *l_store_obj = l_store_obj_all + i; + char l_key[64] = { 0 }; + snprintf(l_key, sizeof(l_key), "KEY$%08zx", i); /* Generate a key of record */ + + dap_assert_PIF(l_store_obj, "Record-Not-Found"); + if (l_store_obj->sign) // to test rewriting with hash conflict some records wiwthout sign + dap_assert_PIF(dap_global_db_pkt_check_sign_crc(l_store_obj), "Record sign not verified"); + dap_assert_PIF(!strcmp(DAP_DB$T_GROUP, l_store_obj->group), "Check group name"); + dap_assert_PIF(!strcmp(l_key, l_store_obj->key), "Check key name"); + + if (l_store_obj->value) { + dap_chain_hash_fast_t csum = { 0 }; + dap_db_test_record_t *prec = (dap_db_test_record_t *) l_store_obj->value; + log_it(L_DEBUG, "Retrieved object: [%s, %s, %zu octets]", l_store_obj->group, l_store_obj->key, + l_store_obj->value_len); + log_it(L_DEBUG, "Record: ['%.*s', %d octets]", prec->len, prec->data, prec->len); + dap_hash_fast(prec->data, prec->len, + &csum); /* Compute a hash of the payload part of the record */ + dap_assert_PIF(memcmp(&csum, &prec->csum, sizeof(dap_chain_hash_fast_t)) == 0, + "Record check sum"); /* Integriry checking ... */ + } + } + dap_store_obj_free(l_store_obj_all, l_count); + dap_pass_msg("read_all check"); + + // without holes + l_count = 0; + s_read_all_without_holes = get_cur_time_nsec(); + l_store_obj_all = dap_global_db_driver_read(DAP_DB$T_GROUP, NULL, &l_count, false); + s_read_all_without_holes = get_cur_time_nsec() - s_read_all_without_holes; + dap_assert_PIF(l_count == a_count - a_count / DAP_DB$SZ_HOLES, "Count of all read records without holes not equal count of write records"); + for (size_t i = 0, j = 0; i < a_count; ++i ) { + if (a_count % DAP_DB$SZ_HOLES) { + dap_chain_hash_fast_t csum = { 0 }; + dap_db_test_record_t *prec = NULL; + dap_store_obj_t *l_store_obj = l_store_obj_all + j; + char l_key[64] = { 0 }; + snprintf(l_key, sizeof(l_key), "KEY$%08zx", i); /* Generate a key of record */ -static void s_test_read_cond_store(size_t a_count) + dap_assert_PIF(l_store_obj, "Record-Not-Found"); + if (l_store_obj->sign) // to test rewriting with hash conflict some records wiwthout sign + dap_assert_PIF(dap_global_db_pkt_check_sign_crc(l_store_obj), "Record sign not verified"); + dap_assert_PIF(!strcmp(DAP_DB$T_GROUP, l_store_obj->group), "Check group name"); + dap_assert_PIF(!strcmp(l_key, l_store_obj->key), "Check key name"); + + prec = (dap_db_test_record_t *) l_store_obj->value; + log_it(L_DEBUG, "Retrieved object: [%s, %s, %zu octets]", l_store_obj->group, l_store_obj->key, + l_store_obj->value_len); + log_it(L_DEBUG, "Record: ['%.*s', %d octets]", prec->len, prec->data, prec->len); + dap_hash_fast(prec->data, prec->len, + &csum); /* Compute a hash of the payload part of the record */ + dap_assert_PIF(memcmp(&csum, &prec->csum, sizeof(dap_chain_hash_fast_t)) == 0, + "Record check sum"); /* Integriry checking ... */ + ++j; + } + } + dap_store_obj_free(l_store_obj_all, l_count); + + return 0; +} + + +static void s_test_read_cond_store(size_t a_count, bool a_bench) { dap_global_db_driver_hash_t l_driver_key = {0}; size_t l_count = 0; - int l_time = 0; for (size_t i = 0; i < a_count; ++i) { - l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); dap_store_obj_t *l_objs = dap_global_db_driver_cond_read(DAP_DB$T_GROUP, l_driver_key, &l_count, true); - s_read_cond_store += get_cur_time_msec() - l_time; + s_read_cond_store += a_bench ? get_cur_time_nsec() - l_time : 0; + dap_assert_PIF(l_objs, "Records-Not-Found"); dap_global_db_driver_hash_t l_blank_check = dap_global_db_driver_hash_get(l_objs + l_count - 1); dap_assert_PIF(l_count <= DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT + dap_global_db_driver_hash_is_blank(&l_blank_check), "Wrong finded records count"); @@ -228,8 +313,7 @@ static void s_test_read_cond_store(size_t a_count) dap_store_obj_free(l_objs, l_count); } - l_time = get_cur_time_msec(); - l_count = 99; + l_count = DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT / 4; l_driver_key = (dap_global_db_driver_hash_t){0}; size_t l_total_count = 0; for (dap_store_obj_t *l_objs = dap_global_db_driver_cond_read(DAP_DB$T_GROUP, l_driver_key, &l_count, true); @@ -242,11 +326,9 @@ static void s_test_read_cond_store(size_t a_count) break; } } - s_read_cond_store += get_cur_time_msec() - l_time; dap_assert_PIF(l_total_count - dap_global_db_driver_hash_is_blank(&l_driver_key) == a_count, "Total cond read count with holes not equal total records count"); - l_time = get_cur_time_msec(); - l_count = 99; + l_count = DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT / 4; l_driver_key = (dap_global_db_driver_hash_t){0}; l_total_count = 0; for (dap_store_obj_t *l_objs = dap_global_db_driver_cond_read(DAP_DB$T_GROUP, l_driver_key, &l_count, false); @@ -259,24 +341,24 @@ static void s_test_read_cond_store(size_t a_count) break; } } - s_read_cond_store += get_cur_time_msec() - l_time; dap_assert_PIF(l_total_count - dap_global_db_driver_hash_is_blank(&l_driver_key) == a_count / DAP_DB$SZ_HOLES * (DAP_DB$SZ_HOLES - 1), "Total cond read count without holes not equal total records count"); dap_pass_msg("read_cond_store check"); } -static void s_test_count(size_t a_count) +static void s_test_count(size_t a_count, bool a_bench) { dap_global_db_driver_hash_t l_driver_key = {0}; - int l_time = 0; for (size_t i = 0; i < a_count; ++i) { char l_key[64] = { 0 }; snprintf(l_key, sizeof(l_key), "KEY$%08zx", i); dap_store_obj_t *l_store_obj = dap_global_db_driver_read(DAP_DB$T_GROUP, l_key, NULL, true); dap_assert_PIF(l_store_obj, "Records-Not-Found"); - l_time = get_cur_time_msec(); - dap_assert_PIF(a_count - i == dap_global_db_driver_count(DAP_DB$T_GROUP, l_driver_key, true), "Count with holes"); - s_count += get_cur_time_msec() - l_time; + uint64_t l_time = get_cur_time_nsec(); + size_t l_count = dap_global_db_driver_count(DAP_DB$T_GROUP, l_driver_key, true); + s_count_with_holes += a_bench ? get_cur_time_nsec() - l_time : 0; + dap_assert_PIF(a_count - i == l_count, "Count with holes"); + l_driver_key = dap_global_db_driver_hash_get(l_store_obj); dap_store_obj_free_one(l_store_obj); @@ -293,9 +375,10 @@ static void s_test_count(size_t a_count) dap_store_obj_t *l_store_obj = dap_global_db_driver_read(DAP_DB$T_GROUP, l_key, NULL, false); dap_assert_PIF(l_store_obj, "Records-Not-Found"); - l_time = get_cur_time_msec(); - dap_assert_PIF(a_count / DAP_DB$SZ_HOLES * (DAP_DB$SZ_HOLES - 1) - k == dap_global_db_driver_count(DAP_DB$T_GROUP, l_driver_key, false), "Count without holes"); - s_count += get_cur_time_msec() - l_time; + uint64_t l_time = get_cur_time_nsec(); + size_t l_count = dap_global_db_driver_count(DAP_DB$T_GROUP, l_driver_key, false); + s_count_without_holes += a_bench ? get_cur_time_nsec() - l_time : 0; + dap_assert_PIF(a_count / DAP_DB$SZ_HOLES * (DAP_DB$SZ_HOLES - 1) - k == l_count, "Count without holes"); l_driver_key = dap_global_db_driver_hash_get(l_store_obj); dap_store_obj_free_one(l_store_obj); @@ -308,14 +391,22 @@ static void s_test_count(size_t a_count) dap_pass_msg("count check"); } -static void s_test_is_obj(size_t a_count) +static void s_test_is_obj(size_t a_count, bool a_bench) { for (size_t i = 0; i < a_count; ++i) { char l_key[64] = { 0 }; snprintf(l_key, sizeof(l_key), "KEY$%08zx", i); /* Generate a key of record */ - dap_assert_PIF(dap_global_db_driver_is(DAP_DB$T_GROUP, l_key), "Key not finded") - dap_assert_PIF(!dap_global_db_driver_is(DAP_DB$T_GROUP_WRONG, l_key), "Key finded in wrong group") - dap_assert_PIF(!dap_global_db_driver_is(DAP_DB$T_GROUP_NOT_EXISTED, l_key), "Key finded in not existed group") + uint64_t l_time = get_cur_time_nsec(); + dap_assert_PIF(dap_global_db_driver_is(DAP_DB$T_GROUP, l_key), "Key not finded"); + s_is_obj += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); + dap_assert_PIF(!dap_global_db_driver_is(DAP_DB$T_GROUP_WRONG, l_key), "Key finded in wrong group"); + s_is_obj_wrong += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); + dap_assert_PIF(!dap_global_db_driver_is(DAP_DB$T_GROUP_NOT_EXISTED, l_key), "Key finded in not existed group"); + s_is_obj_not_existed += a_bench ? get_cur_time_nsec() - l_time : 0; } for (size_t i = a_count; i < a_count * 2; ++i) { char l_key[64] = { 0 }; @@ -327,7 +418,7 @@ static void s_test_is_obj(size_t a_count) dap_pass_msg("is_obj check"); } -static void s_test_is_hash(size_t a_count) +static void s_test_is_hash(size_t a_count, bool a_bench) { for (size_t i = 0; i < a_count; ++i) { char l_key[64] = { 0 }; @@ -336,62 +427,98 @@ static void s_test_is_hash(size_t a_count) dap_assert_PIF(l_store_obj, "Record-Not-Found"); dap_global_db_driver_hash_t l_driver_key = dap_global_db_driver_hash_get(l_store_obj); - int l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); dap_assert_PIF(dap_global_db_driver_is_hash(DAP_DB$T_GROUP, l_driver_key), "Hash not finded") + s_is_hash += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); dap_assert_PIF(!dap_global_db_driver_is_hash(DAP_DB$T_GROUP_WRONG, l_driver_key), "Hash finded in wrong group") + s_is_hash_wrong += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); dap_assert_PIF(!dap_global_db_driver_is_hash(DAP_DB$T_GROUP_NOT_EXISTED, l_driver_key), "Hash finded in not existed group") + s_is_hash_not_existed += a_bench ? get_cur_time_nsec() - l_time : 0; + l_driver_key.becrc = 0; dap_assert_PIF(!dap_global_db_driver_is_hash(DAP_DB$T_GROUP, l_driver_key), "Finded not existed hash") dap_assert_PIF(!dap_global_db_driver_is_hash(DAP_DB$T_GROUP_WRONG, l_driver_key), "Finded not existed hash in wrong group") dap_assert_PIF(!dap_global_db_driver_is_hash(DAP_DB$T_GROUP_NOT_EXISTED, l_driver_key), "Finded not existed hash in not existed group") - s_is_hash = get_cur_time_msec() - l_time; dap_store_obj_free_one(l_store_obj); } dap_pass_msg("is_hash check"); } -static void s_test_last(size_t a_count) +static void s_test_last(size_t a_count, bool a_bench) { char l_key[64] = { 0 }; // with holes snprintf(l_key, sizeof(l_key), "KEY$%08zx", a_count - 1); - dap_store_obj_t *l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP, true); - dap_assert_PIF(l_store_obj && !strcmp(l_key, l_store_obj->key), "Last with holes"); - dap_store_obj_free_one(l_store_obj); + for (size_t i = 0; i < a_count; ++i) { + uint64_t l_time = get_cur_time_nsec(); + dap_store_obj_t *l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP, true); + s_last_with_holes += a_bench ? get_cur_time_nsec() - l_time : 0; + + dap_assert_PIF(l_store_obj && !strcmp(l_key, l_store_obj->key), "Last with holes"); + dap_store_obj_free_one(l_store_obj); + + l_time = get_cur_time_nsec(); + l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_WRONG, true); + s_last_with_holes_wrong += a_bench ? get_cur_time_nsec() - l_time : 0; + + dap_assert_PIF(l_store_obj && strcmp(l_key, l_store_obj->key), "Last with holes in wrong group"); + dap_store_obj_free_one(l_store_obj); + + l_time = get_cur_time_nsec(); + l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_NOT_EXISTED, true); + s_last_with_holes_not_existed += a_bench ? get_cur_time_nsec() - l_time : 0; - l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_WRONG, true); - dap_assert_PIF(l_store_obj && strcmp(l_key, l_store_obj->key), "Last with holes in wrong group"); - dap_store_obj_free_one(l_store_obj); + dap_assert_PIF(!l_store_obj, "Last with holes in not existed group"); + } - l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_NOT_EXISTED, true); - dap_assert_PIF(!l_store_obj, "Last with holes in not existed group"); // without holes snprintf(l_key, sizeof(l_key), "KEY$%08zx", a_count - 1 - a_count % DAP_DB$SZ_HOLES); - l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP, false); - dap_assert_PIF(l_store_obj && !strcmp(l_key, l_store_obj->key), "Last without holes"); - dap_store_obj_free_one(l_store_obj); + + for (size_t i = 0; i < a_count; ++i) { + uint64_t l_time = get_cur_time_nsec(); + dap_store_obj_t *l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP, false); + s_last_without_holes += a_bench ? get_cur_time_nsec() - l_time : 0; - l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_WRONG, false); - dap_assert_PIF(l_store_obj && strcmp(l_key, l_store_obj->key), "Last without holes in wrong group"); - dap_store_obj_free_one(l_store_obj); + dap_assert_PIF(l_store_obj && !strcmp(l_key, l_store_obj->key), "Last without holes"); + dap_store_obj_free_one(l_store_obj); - l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_NOT_EXISTED, false); - dap_assert_PIF(!l_store_obj, "Last without holes in not existed group"); + l_time = get_cur_time_nsec(); + l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_WRONG, false); + s_last_without_holes_wrong += a_bench ? get_cur_time_nsec() - l_time : 0; + + dap_assert_PIF(l_store_obj && strcmp(l_key, l_store_obj->key), "Last without holes in wrong group"); + dap_store_obj_free_one(l_store_obj); + + l_time = get_cur_time_nsec(); + l_store_obj = dap_global_db_driver_read_last(DAP_DB$T_GROUP_NOT_EXISTED, false); + s_last_without_holes_not_existed += a_bench ? get_cur_time_nsec() - l_time : 0; + + dap_assert_PIF(!l_store_obj, "Last without holes in not existed group"); + } dap_pass_msg("read_last check"); } -static void s_test_read_hashes(size_t a_count) +static void s_test_read_hashes(size_t a_count, bool a_bench) { dap_global_db_driver_hash_t l_driver_key = {0}; - int l_time = 0; for (size_t i = 0; i < a_count; ++i) { - l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); dap_global_db_hash_pkt_t *l_hashes = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP, l_driver_key); + s_read_hashes += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); dap_global_db_hash_pkt_t *l_hashes_wrong = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP_WRONG, l_driver_key); + s_read_hashes_wrong += a_bench ? get_cur_time_nsec() - l_time : 0; + + l_time = get_cur_time_nsec(); dap_global_db_hash_pkt_t *l_hashes_not_existed = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP_NOT_EXISTED, l_driver_key); - s_read_hashes += get_cur_time_msec() - l_time; + s_read_hashes_not_existed += a_bench ? get_cur_time_nsec() - l_time : 0; dap_assert_PIF(l_hashes && l_hashes_wrong, "Hashes-Not-Found"); dap_assert_PIF(!l_hashes_not_existed, "Finded hashes in not existed group"); @@ -414,17 +541,15 @@ static void s_test_read_hashes(size_t a_count) dap_pass_msg("read_hashes check"); } -static void s_test_get_by_hash(size_t a_count) +static void s_test_get_by_hash(size_t a_count, bool a_bench) { dap_global_db_driver_hash_t l_driver_key = {0}; - size_t l_count = 99; - int l_time = 0; for (size_t i = 0; i < a_count; ++i) { dap_global_db_hash_pkt_t *l_hashes = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP, l_driver_key); - l_time = get_cur_time_msec(); + uint64_t l_time = get_cur_time_nsec(); dap_global_db_pkt_pack_t *l_objs = dap_global_db_driver_get_by_hash(DAP_DB$T_GROUP, (dap_global_db_driver_hash_t *)(l_hashes->group_n_hashses + l_hashes->group_name_len), l_hashes->hashes_count); - s_get_by_hash += get_cur_time_msec() - l_time; + s_get_by_hash += a_bench ? get_cur_time_nsec() - l_time : 0; dap_assert_PIF(l_objs, "Records-Not-Found"); dap_assert_PIF(l_objs->obj_count == l_hashes->hashes_count - dap_global_db_driver_hash_is_blank((dap_global_db_driver_hash_t *)(l_hashes->group_n_hashses + l_hashes->group_name_len) + l_hashes->hashes_count - 1), "Wrong finded records count"); @@ -458,28 +583,13 @@ static void s_test_get_by_hash(size_t a_count) l_driver_key = (dap_global_db_driver_hash_t){0}; size_t l_total_count = 0; - for (dap_global_db_hash_pkt_t *l_hashes = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP, l_driver_key); - l_hashes; - l_hashes = dap_global_db_driver_hashes_read(DAP_DB$T_GROUP, l_driver_key)) { - l_driver_key = ((dap_global_db_driver_hash_t *)(l_hashes->group_n_hashses + l_hashes->group_name_len))[l_hashes->hashes_count - 1]; - - l_time = get_cur_time_msec(); - dap_global_db_pkt_pack_t *l_objs = dap_global_db_driver_get_by_hash(DAP_DB$T_GROUP, (dap_global_db_driver_hash_t *)(l_hashes->group_n_hashses + l_hashes->group_name_len), l_hashes->hashes_count); - s_get_by_hash += get_cur_time_msec() - l_time; - - l_total_count += l_hashes->hashes_count; - DAP_DEL_MULTY(l_hashes, l_objs); - if (dap_global_db_driver_hash_is_blank(&l_driver_key)) { - break; - } - } - dap_assert_PIF(l_total_count - dap_global_db_driver_hash_is_blank(&l_driver_key) == a_count, "Total get by hash count not equal total records count"); dap_pass_msg("get_by_hash check"); } -static void s_test_get_groups_by_mask() +static void s_test_get_groups_by_mask(size_t a_count, bool a_bench) { dap_list_t *l_groups = NULL; + l_groups = dap_global_db_driver_get_groups_by_mask("group.z*"); dap_assert_PIF(dap_list_length(l_groups) == 1 && !strcmp(DAP_DB$T_GROUP, l_groups->data), "Wrong finded group by mask"); dap_list_free_full(l_groups, NULL); @@ -492,9 +602,14 @@ static void s_test_get_groups_by_mask() dap_assert_PIF(!dap_list_length(l_groups), "Finded not existed groups"); dap_list_free_full(l_groups, NULL); - l_groups = dap_global_db_driver_get_groups_by_mask("group.*"); - dap_assert_PIF(dap_list_length(l_groups) == 2, "Wrong finded groups by mask"); - dap_list_free_full(l_groups, NULL); + for (size_t i = 0; i < a_count; ++i) { + uint64_t l_time = get_cur_time_nsec(); + l_groups = dap_global_db_driver_get_groups_by_mask("group.*"); + s_get_groups_by_mask += a_bench ? get_cur_time_nsec() - l_time : 0; + + dap_assert_PIF(dap_list_length(l_groups) == 2, "Wrong finded groups by mask"); + dap_list_free_full(l_groups, NULL); + } dap_pass_msg("get_groups_by_mask check"); } @@ -505,7 +620,6 @@ static void s_test_flush() static void s_test_tx_start_end(size_t a_count, bool a_missing_allow) { - int l_time = 0; size_t l_count = 0; dap_store_obj_t *l_objs = dap_global_db_driver_cond_read(DAP_DB$T_GROUP, (dap_global_db_driver_hash_t){0}, &l_count, true); dap_global_db_driver_hash_t l_hash_last = dap_global_db_driver_hash_get(l_objs + l_count - 1); @@ -514,9 +628,9 @@ static void s_test_tx_start_end(size_t a_count, bool a_missing_allow) l_objs[i].flags |= DAP_GLOBAL_DB_RECORD_ERASE; } - l_time = get_cur_time_msec(); + s_tx_start_end_erase = get_cur_time_nsec(); int ret = dap_global_db_driver_apply(l_objs, l_count); - s_tx_start_end += get_cur_time_msec() - l_time; + s_tx_start_end_erase = get_cur_time_nsec() - s_tx_start_end_erase; if (!a_missing_allow) { dap_assert_PIF(!ret || ret == DAP_GLOBAL_DB_RC_NOT_FOUND, "Erased records from DB"); @@ -527,9 +641,9 @@ static void s_test_tx_start_end(size_t a_count, bool a_missing_allow) l_objs[i].flags &= ~DAP_GLOBAL_DB_RECORD_ERASE; } - l_time = get_cur_time_msec(); + s_tx_start_end_add = get_cur_time_nsec(); ret = dap_global_db_driver_apply(l_objs, l_count); - s_tx_start_end += get_cur_time_msec() - l_time; + s_tx_start_end_add = get_cur_time_nsec() - s_tx_start_end_add; dap_assert_PIF(!ret, "Restore records to DB"); if (!a_missing_allow) { @@ -547,40 +661,35 @@ static void s_test_close_db(void) } -static void s_test_all(size_t a_count) +static void s_test_all(size_t a_count, bool a_with_value) { - s_test_write(a_count); - s_test_read(a_count); - s_test_read_cond_store(a_count); - s_test_count(a_count); + s_test_write(a_count, a_with_value); + s_test_read(a_count, true); + s_test_read_all(a_count); + s_test_read_cond_store(a_count, true); + s_test_count(a_count, true); s_test_tx_start_end(a_count, false); // if after this tests fail try comment - s_flush = get_cur_time_msec(); + s_flush = get_cur_time_nsec(); s_test_flush(); - s_flush = get_cur_time_msec() - s_flush; + s_flush = get_cur_time_nsec() - s_flush; - s_is_obj = get_cur_time_msec(); - s_test_is_obj(a_count); - s_is_obj = get_cur_time_msec() - s_is_obj; + s_test_is_obj(a_count, true); - s_test_is_hash(a_count); + s_test_is_hash(a_count, true); - s_last = get_cur_time_msec(); - s_test_last(a_count); - s_last = get_cur_time_msec() - s_last; + s_test_last(a_count, true); - s_test_read_hashes(a_count); - s_test_get_by_hash(a_count); + s_test_read_hashes(a_count, true); + s_test_get_by_hash(a_count, true); - s_get_groups_by_mask = get_cur_time_msec(); - s_test_get_groups_by_mask(); - s_get_groups_by_mask = get_cur_time_msec() - s_get_groups_by_mask; + s_test_get_groups_by_mask(a_count, true); } static void *s_test_thread_rewrite_records(void *a_arg) { size_t a_count = *(size_t *)a_arg; - int l_time = 0; + uint64_t l_time = 0; size_t l_count = 0; dap_store_obj_t *l_objs = dap_global_db_driver_cond_read(DAP_DB$T_GROUP, (dap_global_db_driver_hash_t){0}, &l_count, true); if (l_count) { @@ -589,18 +698,14 @@ static void *s_test_thread_rewrite_records(void *a_arg) l_objs[i].flags |= DAP_GLOBAL_DB_RECORD_ERASE; } - l_time = get_cur_time_msec(); int ret = dap_global_db_driver_apply(l_objs, l_count); - s_tx_start_end += get_cur_time_msec() - l_time; // restore erased records for (size_t i = 0; i < l_count; ++i) { l_objs[i].flags &= ~DAP_GLOBAL_DB_RECORD_ERASE; } - l_time = get_cur_time_msec(); ret = dap_global_db_driver_apply(l_objs, l_count); - s_tx_start_end += get_cur_time_msec() - l_time; dap_assert_PIF(!ret, "Restore records to DB"); dap_store_obj_free(l_objs, l_count); @@ -613,16 +718,16 @@ static void *s_test_thread_rewrite_records(void *a_arg) static void *s_test_thread(void *a_arg) { size_t l_count = *(size_t *)a_arg; - s_test_read(l_count); - s_test_read_cond_store(l_count); - s_test_count(l_count); + s_test_read(l_count, false); + s_test_read_cond_store(l_count, false); + s_test_count(l_count, false); s_test_flush(); - s_test_is_obj(l_count); - s_test_is_hash(l_count); - s_test_last(l_count); - s_test_read_hashes(l_count); - s_test_get_by_hash(l_count); - s_test_get_groups_by_mask(); + s_test_is_obj(l_count, false); + s_test_is_hash(l_count, false); + s_test_last(l_count, false); + s_test_read_hashes(l_count, false); + s_test_get_by_hash(l_count, false); + s_test_get_groups_by_mask(l_count, false); pthread_exit(NULL); return NULL; } @@ -668,37 +773,92 @@ static void s_test_multithread(size_t a_count) dap_pass_msg("multithread check"); } -int main(int argc, char **argv) +static void s_test_full(size_t a_db_count, size_t a_count, bool a_with_value) { - dap_log_level_set(L_DEBUG); - size_t l_db_count = sizeof(s_db_types) / sizeof(char *) - 1; - dap_assert_PIF(l_db_count, "Use minimum 1 DB driver"); - size_t l_count = DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT + 2; - for (size_t i = 0; i < l_db_count; ++i) { + for (size_t i = 0; i < a_db_count; ++i) { + s_write = 0; + s_rewrite = 0; + s_read = 0; + s_read_all_with_holes = 0; + s_read_all_without_holes = 0; + s_read_cond_store = 0; + s_count_with_holes = 0; + s_count_without_holes = 0; + s_tx_start_end_erase = 0; + s_tx_start_end_add = 0; + s_flush = 0; + s_is_obj = 0; + s_is_obj_wrong = 0; + s_is_obj_not_existed = 0; + s_is_hash = 0; + s_is_hash_wrong = 0; + s_is_hash_not_existed = 0; + s_last_with_holes = 0; + s_last_without_holes = 0; + s_last_with_holes_wrong = 0; + s_last_without_holes_wrong = 0; + s_last_with_holes_not_existed = 0; + s_last_without_holes_not_existed = 0; + s_read_hashes = 0; + s_read_hashes_wrong = 0; + s_read_hashes_not_existed = 0; + s_get_by_hash = 0; + s_get_groups_by_mask = 0; + dap_print_module_name(s_db_types[i]); s_test_create_db(s_db_types[i]); - int l_t1 = get_cur_time_msec(); - s_test_all(l_count); - int l_t2 = get_cur_time_msec(); + uint64_t l_t1 = get_cur_time_nsec(); + s_test_all(a_count, true); + uint64_t l_t2 = get_cur_time_nsec(); char l_msg[120] = {0}; - sprintf(l_msg, "Tests to %zu records", l_count); - dap_print_module_name("Multithread"); // TODO need update test, fail on pipelines - s_test_multithread(l_count); - dap_print_module_name("Benchmark"); - benchmark_mgs_time(l_msg, l_t2 - l_t1); - benchmark_mgs_time("Tests to write", s_write); - benchmark_mgs_time("Tests to read", s_read); - benchmark_mgs_time("Tests to read_cond_store", s_read_cond_store); - benchmark_mgs_time("Tests to count", s_count); - benchmark_mgs_time("Tests to tx_start_end", s_tx_start_end); - benchmark_mgs_time("Tests to flush", s_flush); - benchmark_mgs_time("Tests to is_obj", s_is_obj); - benchmark_mgs_time("Tests to is_hash", s_is_hash); - benchmark_mgs_time("Tests to last", s_last); - benchmark_mgs_time("Tests to read_hashes", s_read_hashes); - benchmark_mgs_time("Tests to get_by_hash", s_get_by_hash); - benchmark_mgs_time("Tests to get_groups_by_mask", s_get_groups_by_mask); + sprintf(l_msg, "All tests to %zu records", a_count); + dap_print_module_name("Multithread"); + s_test_multithread(a_count); + dap_print_module_name("Benchmark"); + benchmark_mgs_time("Tests to write", s_write / 1000000); + benchmark_mgs_time("Tests to rewrite", s_rewrite / 1000000); + benchmark_mgs_time("Tests to read", s_read / 1000000); + benchmark_mgs_time("Tests to read_all with holes", s_read_all_with_holes / 1000000); + benchmark_mgs_time("Tests to read_all without holes", s_read_all_without_holes / 1000000); + benchmark_mgs_time("Tests to read_cond_store", s_read_cond_store / 1000000); + benchmark_mgs_time("Tests to count with holes", s_count_with_holes / 1000000); + benchmark_mgs_time("Tests to count without holes", s_count_without_holes / 1000000); + benchmark_mgs_time("Tests to tx_start_end erase record", s_tx_start_end_erase / 1000000); + benchmark_mgs_time("Tests to tx_start_end add record", s_tx_start_end_add / 1000000); + benchmark_mgs_time("Tests to flush", s_flush / 1000000); + benchmark_mgs_time("Tests to is_obj", s_is_obj / 1000000); + benchmark_mgs_time("Tests to is_obj in wrong group", s_is_obj_wrong / 1000000); + benchmark_mgs_time("Tests to is_obj in not existed group", s_is_obj_not_existed / 1000000); + benchmark_mgs_time("Tests to is_hash", s_is_hash / 1000000); + benchmark_mgs_time("Tests to is_hash in wrong group", s_is_hash_wrong / 1000000); + benchmark_mgs_time("Tests to is_hash in not existed group", s_is_hash_not_existed / 1000000); + benchmark_mgs_time("Tests to last with holes", s_last_with_holes / 1000000); + benchmark_mgs_time("Tests to last without holes", s_last_without_holes / 1000000); + benchmark_mgs_time("Tests to last with holes in wrong group", s_last_with_holes_wrong / 1000000); + benchmark_mgs_time("Tests to last without holes in wrong group", s_last_without_holes_wrong / 1000000); + benchmark_mgs_time("Tests to last with holes in not existed group", s_last_with_holes_not_existed / 1000000); + benchmark_mgs_time("Tests to last without holes in not existed group", s_last_without_holes_not_existed / 1000000); + benchmark_mgs_time("Tests to read_hashes", s_read_hashes / 1000000); + benchmark_mgs_time("Tests to read_hashes in wrong group", s_read_hashes_wrong / 1000000); + benchmark_mgs_time("Tests to read_hashes in not existed group", s_read_hashes_not_existed / 1000000); + benchmark_mgs_time("Tests to get_by_hash", s_get_by_hash / 1000000); + benchmark_mgs_time("Tests to get_groups_by_mask", s_get_groups_by_mask / 1000000); + benchmark_mgs_time(l_msg, (l_t2 - l_t1) / 1000000); s_test_close_db(); } + +} + +int main(int argc, char **argv) +{ + dap_log_level_set(L_DEBUG); + size_t l_db_count = sizeof(s_db_types) / sizeof(char *) - 1; + dap_assert_PIF(l_db_count, "Use minimum 1 DB driver"); + size_t l_count = DAP_GLOBAL_DB_COND_READ_COUNT_DEFAULT + 2; + dap_assert_PIF(!(l_count % DAP_DB$SZ_HOLES), "If l_count \% DAP_DB$SZ_HOLES tests will fail"); + dap_print_module_name("Tests with value"); + s_test_full(l_db_count, l_count, true); + dap_print_module_name("Tests without value"); + s_test_full(l_db_count, l_count, false); } diff --git a/test-framework/dap_test.c b/test-framework/dap_test.c index 55517435e174987576d3ab75178ddd74fc730193..17f3bae9571c7330d806434ce8a1e8744acbc582 100644 --- a/test-framework/dap_test.c +++ b/test-framework/dap_test.c @@ -36,7 +36,6 @@ void benchmark_mgs_time(const char *test_name, int dt) snprintf(buf, 120, "(%.3lf sec.)", dt * 1. / 1000); } else { - snprintf(buf, 120, "(%d msec.)", dt); } dap_pass_msg_benchmark(test_name, buf); @@ -60,6 +59,18 @@ void benchmark_mgs_rate(const char *test_name, float rate) dap_pass_msg_benchmark(test_name, buf); } + +/** + * @return current time in nanoseconds + */ +uint64_t get_cur_time_nsec(void) +{ + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + return (uint64_t)time.tv_sec * 1000000000 + time.tv_nsec; +} + + /** * @return current time in milliseconds */ diff --git a/test-framework/dap_test.h b/test-framework/dap_test.h index 5af90b49071f6c2312cd6ac611cad31dd3c59708..767aa33431d403365ce59a27a81ba18190e2bb4b 100755 --- a/test-framework/dap_test.h +++ b/test-framework/dap_test.h @@ -5,6 +5,7 @@ #include <stdio.h> #include <string.h> #include <time.h> +#include <bits/stdint-uintn.h> #define TEXT_COLOR_RED "\x1B[31m" #define TEXT_COLOR_GRN "\x1B[32m" @@ -70,6 +71,7 @@ #define dap_str_equals(str1, str2) strcmp(str1, str2) == 0 #define dap_strn_equals(str1, str2, count) strncmp(str1, str2, count) == 0 int get_cur_time_msec(void); +uint64_t get_cur_time_nsec(void); /* How to use benchmark_xxx() functions: