summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchenzizhan <[email protected]>2023-11-24 09:53:52 +0800
committerchenzizhan <[email protected]>2023-11-24 09:53:52 +0800
commita319982221b19b979efa6877f08115c95adec305 (patch)
tree6bf75b9ea71c11c0556b5c7eac556b0feefcd61b
parent30437a0f2756671ba658311c0f179769f2b4e5ea (diff)
reduce malloc. use hash128 to circumvent key cmp
-rw-r--r--src/fieldstat.c39
-rw-r--r--src/tags/my_ut_hash.c108
-rw-r--r--src/tags/my_ut_hash.h15
-rw-r--r--test/profiling/main.c18
-rw-r--r--test/test_easy_fs.cpp120
-rw-r--r--test/test_write_json_file.cpp16
-rw-r--r--test/unit_test_cell_manager.cpp14
7 files changed, 167 insertions, 163 deletions
diff --git a/src/fieldstat.c b/src/fieldstat.c
index b109ad3..dcabddf 100644
--- a/src/fieldstat.c
+++ b/src/fieldstat.c
@@ -281,8 +281,8 @@ struct fs_cube *fieldstat_cube_info_init(const struct fieldstat_tag *shared_tags
cube->n_shared_tags = n_tag;
- struct tag_hash_key *shared_tag_key = tag_hash_key_construct_with_fieldstat_tag(shared_tags, n_tag);
- tag_hash_key_store(shared_tag_key);
+ struct tag_hash_key *shared_tag_key = malloc(sizeof(struct tag_hash_key));
+ tag_hash_key_init_with_fieldstat_tag(shared_tag_key, shared_tags, n_tag, true);
cube->key_tag = shared_tag_key;
cube->max_n_metric = 64;
@@ -316,9 +316,9 @@ int fieldstat_create_cube(struct fieldstat *instance, const struct fieldstat_tag
if (max_n_cell == 0) {
max_n_cell = INT32_MAX;
}
- struct tag_hash_key *shared_tag_key = tag_hash_key_construct_with_fieldstat_tag(shared_tags, n_tag);
- int ret = cube_manager_find(instance->shared_tag_cube_manager, shared_tag_key);
- tag_hash_key_free(shared_tag_key);
+ struct tag_hash_key shared_tag_key;
+ tag_hash_key_init_with_fieldstat_tag(&shared_tag_key, shared_tags, n_tag, false);
+ int ret = cube_manager_find(instance->shared_tag_cube_manager, &shared_tag_key);
if (ret != -1) {
return FS_ERR_INVALID_KEY;
}
@@ -335,12 +335,14 @@ int fieldstat_cube_add(struct fieldstat *instance, int cube_id, const struct fie
struct fs_cube *cube = instance->cube[cube_id];
int ret = -1;
- struct tag_hash_key *tag_key = tag_hash_key_construct_with_fieldstat_tag(tags, n_tag);
+ struct tag_hash_key tag_key;
+
+ tag_hash_key_init_with_fieldstat_tag(&tag_key, tags, n_tag, false);
if (cube->sampling_mode == SAMPLING_MODE_COMPREHENSIVE) {
- ret = cell_manager_add_cell(cube->cell_manager, tag_key);
+ ret = cell_manager_add_cell(cube->cell_manager, &tag_key);
} else {
int popped_cell_id = -1;
- ret = cell_manager_add_cell_topk(cube->cell_manager, tag_key, occurrence, &popped_cell_id);
+ ret = cell_manager_add_cell_topk(cube->cell_manager, &tag_key, occurrence, &popped_cell_id);
if (popped_cell_id != -1) {
for (size_t i = 0; i < cube->valid_metric_arr_len; i++) {
@@ -352,8 +354,6 @@ int fieldstat_cube_add(struct fieldstat *instance, int cube_id, const struct fie
}
}
- tag_hash_key_free(tag_key);
-
if (ret < 0) {
return -1;
}
@@ -598,6 +598,7 @@ int fieldstat_counter_incrby(struct fieldstat *instance, int cube_id, int metric
occurrence = increment;
}
+
int cell_id = fieldstat_cube_add(instance, cube_id, tags, n_tag, occurrence);
if (cell_id < 0) {
return FS_ERR_TOO_MANY_CELLS;
@@ -652,8 +653,9 @@ int fieldstat_counter_set(struct fieldstat *instance, int cube_id, int metric_id
// get the occurrence
long long occurrence = 0;
if (cube->sampling_mode == SAMPLING_MODE_TOPK && cube->primary_metric_id == metric_id) {
- struct tag_hash_key *tag_key = tag_hash_key_construct_with_fieldstat_tag(tags, n_tag);
- cell_id = cell_manager_find(cube->cell_manager, tag_key);
+ struct tag_hash_key tag_key;
+ tag_hash_key_init_with_fieldstat_tag(&tag_key, tags, n_tag, false);
+ cell_id = cell_manager_find(cube->cell_manager, &tag_key);
if (cell_id >= 0) {
long long old_value;
int exist_flag = metric_counter_get(metric, cell_id, &old_value);
@@ -665,7 +667,6 @@ int fieldstat_counter_set(struct fieldstat *instance, int cube_id, int metric_id
} else {
occurrence = value;
}
- tag_hash_key_free(tag_key);
if (occurrence < 0) {
return FS_ERR_INVALID_PARAM;
}
@@ -1190,9 +1191,9 @@ struct fieldstat_tag_list *fieldstat_get_shared_tags(const struct fieldstat *ins
int get_cell_id_by_tag_list(const struct fieldstat *instance, int cube_id, const struct fieldstat_tag_list *tags)
{
- struct tag_hash_key *tag_key = tag_hash_key_construct_with_fieldstat_tag(tags->tag, tags->n_tag);
- int cell_id = cell_manager_find(instance->cube[cube_id]->cell_manager, tag_key);
- tag_hash_key_free(tag_key);
+ struct tag_hash_key tag_key;
+ tag_hash_key_init_with_fieldstat_tag(&tag_key, tags->tag, tags->n_tag, false);
+ int cell_id = cell_manager_find(instance->cube[cube_id]->cell_manager, &tag_key);
return cell_id;
}
@@ -1418,9 +1419,9 @@ int fieldstat_find_cube(const struct fieldstat *instance, const struct fieldstat
return FS_ERR_NULL_HANDLER;
}
const struct cube_manager *tag_cube_id_map = instance->shared_tag_cube_manager;
- struct tag_hash_key *shared_tag_key = tag_hash_key_construct_with_fieldstat_tag(shared_tags, n_shared_tags);
- int cube_id = cube_manager_find(tag_cube_id_map, shared_tag_key);
- tag_hash_key_free(shared_tag_key);
+ struct tag_hash_key shared_tag_key;
+ tag_hash_key_init_with_fieldstat_tag(&shared_tag_key, shared_tags, n_shared_tags, false);
+ int cube_id = cube_manager_find(tag_cube_id_map, &shared_tag_key);
if (cube_id == -1) {
return FS_ERR_INVALID_KEY;
}
diff --git a/src/tags/my_ut_hash.c b/src/tags/my_ut_hash.c
index 0e166c8..b901e81 100644
--- a/src/tags/my_ut_hash.c
+++ b/src/tags/my_ut_hash.c
@@ -11,19 +11,12 @@
#include "serializer.h"
-struct tag_hash_key {
-
- struct fieldstat_tag *tags; // not used for hash, just to recover the original tags.
- size_t n_my_tag;
- unsigned int hashv;
- bool is_deep_copy;
-};
-
unsigned int tag_hash_key_cal_hash_value(const struct tag_hash_key *my_hash_key)
{
return my_hash_key->hashv;
}
+// used by HASH_FIND
int tag_hash_key_cmp(const struct tag_hash_key *a, const struct tag_hash_key *b)
{
if (a->n_my_tag == 0 && b->n_my_tag == 0) {
@@ -33,6 +26,10 @@ int tag_hash_key_cmp(const struct tag_hash_key *a, const struct tag_hash_key *b)
if (a->n_my_tag != b->n_my_tag) {
return 1;
}
+ if (a->hashv128.high64 != b->hashv128.high64 || a->hashv128.low64 != b->hashv128.low64) {
+ return 1;
+ }
+
size_t tmp_tag_n = a->n_my_tag;
const struct fieldstat_tag *tag_a = a->tags;
const struct fieldstat_tag *tag_b = b->tags;
@@ -47,7 +44,7 @@ int tag_hash_key_cmp(const struct tag_hash_key *a, const struct tag_hash_key *b)
}
}
- // its hardly possible that the key is different while the value is the same. What's more, the tags are in the same hash bucket. So it's not necessary to compare the key.
+ // its hardly possible that the keys are different while the value is the same. What's more, the tags are in the same 128 hash. So it's not necessary to compare the key.
// if (strcmp(tag_a->key, tag_b->key) != 0) {
// return 1;
// }
@@ -122,38 +119,11 @@ int my_cmp_tag(const void *a, const void *b)
}
}
-#define FNV_HASH_FACTOR 16777619U
-#define FNV_HASH_OFFSET 2166136261U
-
-struct fnv_hash_calculator {
- unsigned int hashv;
-};
-
-void fnv_hash_calculator_init(struct fnv_hash_calculator *calculator, unsigned int seed)
-{
- calculator->hashv = FNV_HASH_OFFSET + (seed * 15);
-}
-
-void fnv_hash_calculator_update(struct fnv_hash_calculator *calculator, const char *key, size_t key_len)
-{
- unsigned int hashv = calculator->hashv;
- for (size_t i = 0; i < key_len; i++) {
- hashv = hashv ^ key[i];
- hashv = hashv * FNV_HASH_FACTOR;
- }
- calculator->hashv = hashv;
-}
-
-unsigned int fnv_hash_calculator_get_hashv(const struct fnv_hash_calculator *calculator)
-{
- return calculator->hashv;
-}
-
unsigned int cal_tag_hash_xxhash(const struct fieldstat_tag *tag, size_t n_tag, unsigned int seed)
{
XXH32_state_t state;
XXH32_reset(&state, seed);
-
+
for (int i = 0; i < n_tag; i++)
{
XXH32_update(&state, (const xxh_u8 *)tag[i].key, strlen(tag[i].key));
@@ -168,41 +138,50 @@ unsigned int cal_tag_hash_xxhash(const struct fieldstat_tag *tag, size_t n_tag,
return XXH32_digest(&state);
}
-unsigned int my_tag_hash_func(struct fieldstat_tag *tags, size_t n_tag)
-{
- return cal_tag_hash_xxhash(tags, n_tag, 0);
-}
-
-struct tag_hash_key *tag_hash_key_construct_with_fieldstat_tag(const struct fieldstat_tag *src, size_t n_src)
+XXH128_hash_t cal_tag_hash_xxhash128(const struct fieldstat_tag *tag, size_t n_tag, unsigned int seed)
{
- struct tag_hash_key *ret_hash_key = (struct tag_hash_key *)malloc(sizeof(struct tag_hash_key));
-
- ret_hash_key->tags = n_src == 0 ? NULL : (struct fieldstat_tag *)src;
- ret_hash_key->n_my_tag = n_src;
- ret_hash_key->is_deep_copy = false;
+ XXH3_state_t *state = XXH3_createState();
+ XXH3_128bits_reset_withSeed(state, seed);
+
+ for (int i = 0; i < n_tag; i++)
+ {
+ // XXH32_update(&state, (const xxh_u8 *)tag[i].key, strlen(tag[i].key));
+ XXH3_128bits_update(state, tag[i].key, strlen(tag[i].key));
- ret_hash_key->n_my_tag = n_src;
+ if (tag[i].type != TAG_CSTRING) { // sizeof(long long) == sizeof(double)
+ XXH3_128bits_update(state, &tag[i].value_longlong, sizeof(long long));
+ } else {
+ XXH3_128bits_update(state, tag[i].value_str, strlen(tag[i].value_str));
+ }
+ }
- // calculate hash value
- ret_hash_key->hashv = my_tag_hash_func(ret_hash_key->tags, ret_hash_key->n_my_tag);
+ XXH128_hash_t ret = XXH3_128bits_digest(state);
+ XXH3_freeState(state);
- return ret_hash_key;
+ return ret;
}
-void tag_hash_key_store(struct tag_hash_key *tag_key)
+void tag_hash_key_init_with_fieldstat_tag(struct tag_hash_key *tag_key, const struct fieldstat_tag *src, size_t n_src, bool deep_copy)
{
- if (tag_key->is_deep_copy) {
- return;
- }
- tag_key->is_deep_copy = true;
- if (tag_key->n_my_tag == 0) {
+ tag_key->n_my_tag = n_src;
+ tag_key->is_deep_copy = deep_copy;
+ if (n_src == 0) {
+ tag_key->tags = NULL;
+ tag_key->hashv = 0;
return;
}
- struct fieldstat_tag *new_tags = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * tag_key->n_my_tag);
- for (int i = 0; i < tag_key->n_my_tag; i++) {
- fieldtag_copy(&new_tags[i], &tag_key->tags[i]);
+
+ tag_key->hashv128 = cal_tag_hash_xxhash128(src, n_src, 0);
+ tag_key->hashv = tag_key->hashv128.high64 ^ tag_key->hashv128.low64;
+
+ if (deep_copy) {
+ tag_key->tags = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * n_src);
+ for (int i = 0; i < (int)n_src; i++) {
+ fieldtag_copy(&tag_key->tags[i], &src[i]);
+ }
+ } else {
+ tag_key->tags = (struct fieldstat_tag *)src;
}
- tag_key->tags = new_tags;
}
void tag_hash_key_convert_to_fieldstat_tag(const struct tag_hash_key *tag_key, struct fieldstat_tag **out, size_t *n_out)
@@ -228,6 +207,7 @@ struct tag_hash_key *tag_hash_key_copy(const struct tag_hash_key *src)
dst->n_my_tag = src->n_my_tag;
dst->hashv = src->hashv;
dst->is_deep_copy = true;
+ dst->hashv128 = src->hashv128;
if (dst->n_my_tag == 0) {
dst->tags = NULL;
@@ -249,13 +229,15 @@ void tag_hash_key_free(struct tag_hash_key *tag_key)
free(tag_key);
}
+// todo: 可能可以在每次操作的时候,都和之前比一次cell id对应的tag,如果tag对上了,就沿用上次的cell id。
+// 也许吧。
+
// FNV-1a hash (http://www.isthe.com/chongo/tech/comp/fnv/)
unsigned tag_hash_key_cal_hash_val(const struct tag_hash_key *tag, unsigned seed) {
// return cal_tag_hash(tag->tags, tag->n_my_tag, seed);
return cal_tag_hash_xxhash(tag->tags, tag->n_my_tag, seed);
}
-
void build_dynamic_cell_key(const struct fieldstat_tag tags[], size_t n_tags, char **out_key, size_t *out_key_size)
{
if (n_tags == 0) {
diff --git a/src/tags/my_ut_hash.h b/src/tags/my_ut_hash.h
index 0cb0e49..1066569 100644
--- a/src/tags/my_ut_hash.h
+++ b/src/tags/my_ut_hash.h
@@ -7,16 +7,21 @@ extern "C"
#endif
#include "fieldstat.h"
+#include "xxhash/xxhash.h"
-struct tag_hash_key;
+struct tag_hash_key {
+ struct fieldstat_tag *tags; // not used for hash, just to recover the original tags.
+ size_t n_my_tag;
+ unsigned int hashv;
+ XXH128_hash_t hashv128;
+ bool is_deep_copy;
+};
-// note that: As to improve performance, the tag_hash_key is a shallow copy of fieldstat_tag, just after been constructed by `tag_hash_key_construct_with_fieldstat_tag`. Use `tag_hash_key_store` to make it a deep copy.
-struct tag_hash_key *tag_hash_key_construct_with_fieldstat_tag(const struct fieldstat_tag *src, size_t n_src);
+void tag_hash_key_init_with_fieldstat_tag(struct tag_hash_key *tag_key, const struct fieldstat_tag *src, size_t n_src, bool deep_copy);
void tag_hash_key_convert_to_fieldstat_tag(const struct tag_hash_key *tag_key, struct fieldstat_tag **out, size_t *n_out);
-struct tag_hash_key *tag_hash_key_copy(const struct tag_hash_key *src); // Deep copy
+struct tag_hash_key *tag_hash_key_copy(const struct tag_hash_key *src); // Always deep copy
void tag_hash_key_free(struct tag_hash_key *tag_key);
unsigned tag_hash_key_cal_hash_val(const struct tag_hash_key *tag, unsigned seed);
-void tag_hash_key_store(struct tag_hash_key *tag_key); // let the shallow copy of fieldstat_tag in tag_key to be deep copy, if they are shallow copy
void fieldtag_list_free(struct fieldstat_tag *tags, size_t n_tags);
char *tag_hash_key_get_compound_key(const struct tag_hash_key *tag);
diff --git a/test/profiling/main.c b/test/profiling/main.c
index 652f107..caf6542 100644
--- a/test/profiling/main.c
+++ b/test/profiling/main.c
@@ -7,7 +7,7 @@
#include "tags/my_ut_hash.h"
#include "tags/my_ut_hash_inner.h"
-#define ADD_OPER_NUM 5000000
+#define ADD_OPER_NUM 5000000ULL
// #define ADD_OPER_NUM 1
#define MAX_STRING_KEY_LEN 10
@@ -19,11 +19,17 @@ const struct fieldstat_tag TEST_TAG_INT = {"INT key_", TAG_INTEGER, {.value_long
int main () {
printf("Start profiling...\n");
clock_t start, end;
+ // struct fieldstat_tag TAG[4] = {
+ // {"INT key_", TAG_INTEGER, {.value_longlong = 100}},
+ // {"STRING key_", TAG_CSTRING, {.value_str = "10012312312312"}},
+ // {"STRING key_", TAG_CSTRING, {.value_str = "100adsffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},
+ // {"FLOAT key_", TAG_INTEGER, {.value_double = 100.0}},
+ // };
struct fieldstat_tag TAG[4] = {
- {"INT key_", TAG_INTEGER, {.value_longlong = 100}},
- {"STRING key_", TAG_CSTRING, {.value_str = "10012312312312"}},
- {"STRING key_", TAG_CSTRING, {.value_str = "100adsffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}},
- {"FLOAT key_", TAG_INTEGER, {.value_double = 100.0}},
+ {"object_id", TAG_INTEGER, {.value_longlong = 20}},
+ {"item_id", TAG_INTEGER, {.value_longlong = 16916397}},
+ {"chart_id", TAG_INTEGER, {.value_longlong = 1}},
+ {"version", TAG_INTEGER, {.value_longlong = 1}},
};
struct fieldstat *instance = fieldstat_new();
@@ -32,7 +38,7 @@ int main () {
start = clock();
// getchar();
- for (int i = 0; i < ADD_OPER_NUM; i++)
+ for (size_t i = 0; i < ADD_OPER_NUM; i++)
{
fieldstat_counter_incrby(instance, 0, 0, TAG, 4, 1);
}
diff --git a/test/test_easy_fs.cpp b/test/test_easy_fs.cpp
index 1bb46b4..8c752e5 100644
--- a/test/test_easy_fs.cpp
+++ b/test/test_easy_fs.cpp
@@ -136,67 +136,67 @@ TEST(test_easy_fieldstat, empty_tag)
remove(FILENAME);
}
-// extern "C" {
-// extern char *fs_easy_output_to_json(struct fieldstat_easy *fs, struct timeval *timestamp);
-// }
-
-// int g_output_count = 0;
-// char *fs_easy_output_to_json_stub(struct fieldstat_easy *fs, struct timeval *timestamp)
-// {
-// g_output_count++;
-// return NULL;
-// }
-
-// TEST(test_easy_fieldstat, output_interval_ok)
-// {
-// Stub stub;
-// stub.set(fs_easy_output_to_json, fs_easy_output_to_json_stub);
-
-// struct fieldstat_easy *fse = fieldstat_easy_new(10, NULL, NULL, 0);
-// fieldstat_easy_register_histogram(fse, "metric histogram", 1, 100000, 3); // a pretty time consuming metric
-// fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_INT, 1, 1);
-// fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_DOUBLE, 1, 10);
-// fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_STRING, 1, 110);
-
-// fieldstat_easy_enable_auto_output(fse, FILENAME, 1);
-
-// sleep(30); // output 30s/1s = 20 times
-// fieldstat_easy_free(fse);
-
-// EXPECT_TRUE(g_output_count == 30 || g_output_count == 29); // missing only one is ok and expected
-// }
-
-// TEST(test_easy_fieldstat, ensure_data_racing_of_two_output_and_of_incyby)
-// {
-// const int N_THREADS = 3;
-// struct fieldstat_tag global_tags[1];
-// struct fieldstat_tag tmptag;
-// tmptag.key = "app id";
-// tmptag.type = TAG_INTEGER;
-// tmptag.value_longlong = 1;
-// global_tags[0] = tmptag;
+extern "C" {
+ extern char *fs_easy_output_to_json(struct fieldstat_easy *fs, struct timeval *timestamp);
+}
+
+int g_output_count = 0;
+char *fs_easy_output_to_json_stub(struct fieldstat_easy *fs, struct timeval *timestamp)
+{
+ g_output_count++;
+ return NULL;
+}
+
+TEST(test_easy_fieldstat, output_interval_ok)
+{
+ Stub stub;
+ stub.set(fs_easy_output_to_json, fs_easy_output_to_json_stub);
+
+ struct fieldstat_easy *fse = fieldstat_easy_new(10, NULL, NULL, 0);
+ fieldstat_easy_register_histogram(fse, "metric histogram", 1, 100000, 3); // a pretty time consuming metric
+ fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_INT, 1, 1);
+ fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_DOUBLE, 1, 10);
+ fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_STRING, 1, 110);
+
+ fieldstat_easy_enable_auto_output(fse, FILENAME, 1);
+
+ sleep(30); // output 30s/1s = 20 times
+ fieldstat_easy_free(fse);
+
+ EXPECT_TRUE(g_output_count == 30 || g_output_count == 29); // missing only one is ok and expected
+}
+
+TEST(test_easy_fieldstat, ensure_data_racing_of_two_output_and_of_incyby)
+{
+ const int N_THREADS = 3;
+ struct fieldstat_tag global_tags[1];
+ struct fieldstat_tag tmptag;
+ tmptag.key = "app id";
+ tmptag.type = TAG_INTEGER;
+ tmptag.value_longlong = 1;
+ global_tags[0] = tmptag;
-// struct fieldstat_easy *fse = fieldstat_easy_new(N_THREADS, NULL, global_tags, 1);
-// int counter_id = fieldstat_easy_register_counter(fse, "incoming bytes");
-// int hdr_id = fieldstat_easy_register_histogram(fse, "delay", 1, 10000, 1);
-// fieldstat_easy_enable_auto_output(fse, FILENAME, 1);
-
-// std::thread threads[N_THREADS];
-// for (int thread_id = 0; thread_id < N_THREADS; thread_id++) {
-// threads[thread_id] = std::thread([fse, counter_id, hdr_id, thread_id]() {
-// for (int i = 0; i < 1000000; i++) { // loop million times to ensure no core dump
-// fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_TAG_INT, 1, 1);
-// fieldstat_easy_histogram_record(fse, thread_id, hdr_id, &TEST_TAG_INT, 1, rand() % 10000);
-// }
-// });
-// }
-// for (int i = 0; i < N_THREADS; i++) {
-// threads[i].join();
-// }
-// fieldstat_easy_free(fse);
-
-// remove(FILENAME);
-// }
+ struct fieldstat_easy *fse = fieldstat_easy_new(N_THREADS, NULL, global_tags, 1);
+ int counter_id = fieldstat_easy_register_counter(fse, "incoming bytes");
+ int hdr_id = fieldstat_easy_register_histogram(fse, "delay", 1, 10000, 1);
+ fieldstat_easy_enable_auto_output(fse, FILENAME, 1);
+
+ std::thread threads[N_THREADS];
+ for (int thread_id = 0; thread_id < N_THREADS; thread_id++) {
+ threads[thread_id] = std::thread([fse, counter_id, hdr_id, thread_id]() {
+ for (int i = 0; i < 1000000; i++) { // loop million times to ensure no core dump
+ fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_TAG_INT, 1, 1);
+ fieldstat_easy_histogram_record(fse, thread_id, hdr_id, &TEST_TAG_INT, 1, rand() % 10000);
+ }
+ });
+ }
+ for (int i = 0; i < N_THREADS; i++) {
+ threads[i].join();
+ }
+ fieldstat_easy_free(fse);
+
+ remove(FILENAME);
+}
int main(int argc, char **argv)
{
diff --git a/test/test_write_json_file.cpp b/test/test_write_json_file.cpp
index 4767952..01023bc 100644
--- a/test/test_write_json_file.cpp
+++ b/test/test_write_json_file.cpp
@@ -9,14 +9,14 @@
const int N_THREAD = 2;
-static struct fieldstat_easy *get_hll_fieldstat_easy()
-{
- /*
- fieldstat easy does not support hll
- */
- assert(0);
- return NULL;
-}
+// static struct fieldstat_easy *get_hll_fieldstat_easy()
+// {
+// /*
+// fieldstat easy does not support hll
+// */
+// assert(0);
+// return NULL;
+// }
extern "C" {
extern char *fs_easy_output_to_json(struct fieldstat_easy *fs, const struct timeval *timestamp, const struct timeval *timestamp_delta);
diff --git a/test/unit_test_cell_manager.cpp b/test/unit_test_cell_manager.cpp
index 958d982..a9c9190 100644
--- a/test/unit_test_cell_manager.cpp
+++ b/test/unit_test_cell_manager.cpp
@@ -10,6 +10,7 @@
#include "fieldstat.h"
#include "tags/cell_manager.h"
#include "utils.hpp"
+#include "tags/my_ut_hash.h"
using namespace std;
@@ -21,8 +22,8 @@ struct tag_hash_key *test_gen_tag_key(const char *key, int value)
{.value_str = strdup(to_string(value).c_str())},
};
- struct tag_hash_key *tag_key = tag_hash_key_construct_with_fieldstat_tag(&tag, 1);
- tag_hash_key_store(tag_key);
+ struct tag_hash_key *tag_key = (struct tag_hash_key *)malloc(sizeof(struct tag_hash_key));
+ tag_hash_key_init_with_fieldstat_tag(tag_key, &tag, 1, true);
free((void *)tag.value_str);
@@ -398,6 +399,15 @@ void add_key_and_assert_find_result_comprehensive(struct cell_manager *cm, const
EXPECT_TRUE(test_is_tag_equal(key_get, key));
}
+struct tag_hash_key *tag_hash_key_construct_with_fieldstat_tag(const struct fieldstat_tag *src, size_t n_src)
+{
+ struct tag_hash_key *ret_hash_key = (struct tag_hash_key *)malloc(sizeof(struct tag_hash_key));
+
+ tag_hash_key_init_with_fieldstat_tag(ret_hash_key, src, n_src, false);
+
+ return ret_hash_key;
+}
+
TEST(unit_test_cell_manager, add_with_key_length_is_1_int_type_topk)
{
struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10);