From 702f5de60d5f218df4af089f0c377a01e68c8401 Mon Sep 17 00:00:00 2001 From: hwwang Date: Sat, 20 Jul 2024 20:40:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAhash=E8=A1=A8=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 4 +- data.txt | 1 + hey.txt | 46 +++++++++++++ hey1.txt | 46 +++++++++++++ runtime/include/map.h | 121 ++++++++++++++++++++++------------ runtime/include/xmalloc.h | 4 +- runtime/src/current_sandbox.c | 47 ++++++++----- runtime/src/module.c | 21 +++--- runtime_sandbox_perf_log.log | 1 + sledge.log | 1 + 10 files changed, 219 insertions(+), 73 deletions(-) create mode 100644 data.txt create mode 100644 hey.txt create mode 100644 hey1.txt diff --git a/.vscode/settings.json b/.vscode/settings.json index 39ad760..57f1eb7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -105,7 +105,9 @@ "hashmap.h": "c", "mutex": "cpp", "xmalloc.h": "c", - "stddef.h": "c" + "stddef.h": "c", + "__mutex_base": "c", + "memory": "c" }, "files.exclude": { "**/.git": true, diff --git a/data.txt b/data.txt new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/data.txt @@ -0,0 +1 @@ +10 diff --git a/hey.txt b/hey.txt new file mode 100644 index 0000000..5d5aeac --- /dev/null +++ b/hey.txt @@ -0,0 +1,46 @@ + +Summary: + Total: 12.2647 secs + Slowest: 3.3362 secs + Fastest: 0.5028 secs + Average: 2.1634 secs + Requests/sec: 49.5730 + + Total data: 27968 bytes + Size/request: 46 bytes + +Response time histogram: + 0.503 [1] | + 0.786 [16] |■■■■ + 1.069 [17] |■■■■ + 1.353 [17] |■■■■ + 1.636 [19] |■■■■ + 1.919 [112] |■■■■■■■■■■■■■■■■■■■■■■■■■ + 2.203 [176] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ + 2.486 [121] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■ + 2.769 [22] |■■■■■ + 3.053 [27] |■■■■■■ + 3.336 [80] |■■■■■■■■■■■■■■■■■■ + + +Latency distribution: + 10% in 1.5052 secs + 25% in 1.8882 secs + 50% in 2.1174 secs + 75% in 2.3524 secs + 90% in 3.1907 secs + 95% in 3.2670 secs + 99% in 3.3261 secs + +Details (average, fastest, slowest): + DNS+dialup: 0.0150 secs, 0.5028 secs, 3.3362 secs + DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs + req write: 0.0057 secs, 0.0000 secs, 0.1496 secs + resp wait: 2.1384 secs, 0.3501 secs, 3.3357 secs + resp read: 0.0002 secs, 0.0000 secs, 0.0169 secs + +Status code distribution: + [200] 608 responses + + + diff --git a/hey1.txt b/hey1.txt new file mode 100644 index 0000000..c113ade --- /dev/null +++ b/hey1.txt @@ -0,0 +1,46 @@ + +Summary: + Total: 11.2523 secs + Slowest: 2.9288 secs + Fastest: 0.0329 secs + Average: 1.2459 secs + Requests/sec: 90.8258 + + Total data: 47012 bytes + Size/request: 46 bytes + +Response time histogram: + 0.033 [1] | + 0.322 [18] |■ + 0.612 [23] |■ + 0.902 [26] |■ + 1.191 [127] |■■■■■■■ + 1.481 [740] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ + 1.770 [59] |■■■ + 2.060 [17] |■ + 2.350 [8] | + 2.639 [1] | + 2.929 [2] | + + +Latency distribution: + 10% in 1.1377 secs + 25% in 1.2114 secs + 50% in 1.2531 secs + 75% in 1.3035 secs + 90% in 1.4574 secs + 95% in 1.5758 secs + 99% in 2.0799 secs + +Details (average, fastest, slowest): + DNS+dialup: 0.0004 secs, 0.0329 secs, 2.9288 secs + DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0000 secs + req write: 0.0001 secs, 0.0000 secs, 0.0179 secs + resp wait: 1.2442 secs, 0.0245 secs, 2.9283 secs + resp read: 0.0001 secs, 0.0000 secs, 0.0005 secs + +Status code distribution: + [200] 1022 responses + + + diff --git a/runtime/include/map.h b/runtime/include/map.h index 89fa83a..e00d278 100644 --- a/runtime/include/map.h +++ b/runtime/include/map.h @@ -4,10 +4,18 @@ #include #include #include +#include -#include "lock.h" + +//#include "lock.h" #include "xmalloc.h" +typedef pthread_mutex_t mutex_lock_t; +#define LOCK_INIT_MX(lock) pthread_mutex_init(lock, NULL) +#define LOCK_LOCK_MX(lock) pthread_mutex_lock(lock) +#define LOCK_UNLOCK_MX(lock) pthread_mutex_unlock(lock) + + /* Simple K-V store based on The Practice of Programming by Kernighan and Pike */ /* Bucket count is sized to be a prime that is approximately 20% larger than the desired capacity (6k keys) */ @@ -25,7 +33,7 @@ struct map_node { }; struct map_bucket { - lock_t lock; + mutex_lock_t lock; struct map_node *head; }; @@ -38,7 +46,7 @@ map_init(struct hashmap *restrict map) { for (int i = 0; i < MAP_BUCKET_COUNT; i++) { map->buckets[i].head = NULL; - LOCK_INIT(&map->buckets[i].lock); + LOCK_INIT_MX(&map->buckets[i].lock); } } @@ -68,9 +76,10 @@ map_get(struct hashmap *map, char *key, uint32_t key_len, uint32_t *ret_value_le struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; - LOCK_LOCK(&bucket->lock); + LOCK_LOCK_MX(&bucket->lock); for (struct map_node *node = bucket->head; node != NULL; node = node->next) { - if (node->hash == hash) { + if (node->hash == hash && memcmp(node->key, key, key_len) == 0) { + value = node->value; *ret_value_len = node->value_len; goto DONE; @@ -80,10 +89,13 @@ map_get(struct hashmap *map, char *key, uint32_t key_len, uint32_t *ret_value_le if (value == NULL) *ret_value_len = 0; DONE: - LOCK_UNLOCK(&bucket->lock); + LOCK_UNLOCK_MX(&bucket->lock); return value; } +/** + * @manage_mvalue manage _ mvalue determines whether the hash table or the caller manages value memory, and true is managed by the hash. + */ static inline bool map_set(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32_t value_len, bool manage_mvalue) { @@ -92,10 +104,10 @@ map_set(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32_t uint32_t hash = MAP_HASH(key, key_len); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; - LOCK_LOCK(&bucket->lock); + LOCK_LOCK_MX(&bucket->lock); for (struct map_node *node = bucket->head; node != NULL; node = node->next) { - if (node->hash == hash) goto DONE; + if (node->hash == hash && memcmp(node->key, key, key_len) == 0) goto DONE; } struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); @@ -118,7 +130,7 @@ map_set(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32_t did_set = true; DONE: - LOCK_UNLOCK(&bucket->lock); + LOCK_UNLOCK_MX(&bucket->lock); return did_set; } @@ -132,33 +144,30 @@ map_delete(struct hashmap *map, char *key, uint32_t key_len) uint32_t hash = MAP_HASH(key, key_len); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; - LOCK_LOCK(&bucket->lock); - - struct map_node *prev = bucket->head; - if (prev != NULL && prev->hash == hash) { - bucket->head = prev->next; - free(prev->key); - if (prev->manage_mvalue) { - free(prev->value); + LOCK_LOCK_MX(&bucket->lock); + + struct map_node *prev = NULL; + struct map_node *node = bucket->head; + while (node != NULL) { + if (node->hash == hash && memcmp(node->key, key, key_len) == 0) { + if (prev == NULL) { + bucket->head = node->next; + } else { + prev->next = node->next; + } + free(node->key); + free(node); + if (node->manage_mvalue) { + free(node->value); + } + did_delete = true; + break; } - free(prev); - did_delete = true; - goto DONE; - } - - for (struct map_node *node = prev->next; node != NULL; prev = node, node = node->next) { - prev->next = node->next; - free(node->key); - if (node->manage_mvalue) { - free(node->value); - } - free(node); - did_delete = true; - goto DONE; - } + prev = node; + node = node->next; + } -DONE: - LOCK_UNLOCK(&bucket->lock); + LOCK_UNLOCK_MX(&bucket->lock); return did_delete; } @@ -167,23 +176,22 @@ map_upsert(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32 { uint32_t hash = MAP_HASH(key, key_len); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; - LOCK_LOCK(&bucket->lock); + LOCK_LOCK_MX(&bucket->lock); for (struct map_node *node = bucket->head; node != NULL; node = node->next) { - if (node->hash == hash) { + if (node->hash == hash && memcmp(node->key, key, key_len) == 0) { node->value_len = value_len; node->value = realloc(node->value, value_len); - //node->value = value; assert(node->value); if (node->manage_mvalue) { memcpy(node->value, value, value_len); - } + }else node->value = value; goto DONE; } } - - struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); + panic("map_upsert: key not found"); + /*struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); *(new_node) = (struct map_node){ .hash = hash, .key = xmalloc(key_len), @@ -199,8 +207,37 @@ map_upsert(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32 memcpy(new_node->key, key, key_len); memcpy(new_node->value, value, value_len); - bucket->head = new_node; + bucket->head = new_node;*/ DONE: - LOCK_UNLOCK(&bucket->lock); + LOCK_UNLOCK_MX(&bucket->lock); } + +/*static inline void +map_destroy(struct hashmap *map) { + for (int i = 0; i < MAP_BUCKET_COUNT; i++) { + LOCK_LOCK_MX(&map->buckets[i].lock); + struct map_node *current = map->buckets[i].head; + struct map_node *next; + + while (current != NULL) { + next = current->next; + free(current->key); + if (current->manage_mvalue && current->value != NULL) { + free(current->value); + } + free(current); + current = next; + } + + LOCK_UNLOCK_MX(&map->buckets[i].lock); + + pthread_mutex_destroy(&map->buckets[i].lock); + + // 确保头指针设置为 NULL + map->buckets[i].head = NULL; + } + // 如果 hashmap 是动态分配的,这里还需要释放 hashmap 结构本身 + // free(map); +}*/ + diff --git a/runtime/include/xmalloc.h b/runtime/include/xmalloc.h index 8860568..8449da0 100644 --- a/runtime/include/xmalloc.h +++ b/runtime/include/xmalloc.h @@ -3,12 +3,12 @@ #include #include "likely.h" -//#include "panic.h" +#include "panic.h" static inline void * xmalloc(size_t size) { void *allocation = malloc(size); - //if (unlikely(allocation == NULL)) panic("xmalloc failed!\n"); + if (unlikely(allocation == NULL)) panic("xmalloc failed!\n"); return allocation; } diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index df7de09..39fba5c 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -12,6 +12,7 @@ #include "hashmap.h" extern uint64_t system_start_timestamp; +pthread_mutex_t lock; __thread struct sandbox *worker_thread_current_sandbox = NULL; @@ -142,9 +143,9 @@ current_sandbox_start(void) } else if (next_module != NULL) { assert(next_module_idx); assert(next_module); - size_t next_module_pre_count_flag = next_module[0]->pre_module_count; - assert(next_module_pre_count_flag); - if (next_module_idx > 1 || (next_module_idx == 1 && next_module_pre_count_flag == 1)) + size_t next_module_pre_count = next_module[0]->pre_module_count; + assert(next_module_pre_count); + if (next_module_idx > 1 || (next_module_idx == 1 && next_module_pre_count == 1)) { /* Generate a new request, copy the current sandbox's output to the next request's buffer, and put it to the global queue */ ssize_t output_length = sandbox->request_response_data_length - sandbox->request_length; @@ -200,8 +201,10 @@ current_sandbox_start(void) sandbox_remove_from_epoll(sandbox); } sandbox_set_as_returned(sandbox, SANDBOX_RUNNING); - }else if (next_module_idx == 1 && next_module_pre_count_flag > 1) + }else if (next_module_idx == 1 && next_module_pre_count > 1) { + pthread_mutex_init(&lock, NULL); + pthread_mutex_lock(&lock); /*Before each id is put into the hash table, the key needs to add a "module handle"*/ struct module * next_module_node = next_module[0]; assert(next_module_node); @@ -243,6 +246,7 @@ current_sandbox_start(void) assert(module_pre_count); map_set(sandbox_request_id, cur_request_id, strlen(cur_request_id), &module_pre_count, sizeof(uint32_t), true); map_set(sandbox_req_map, cur_request_id, strlen(cur_request_id), sandbox_request, sizeof(struct sandbox_request *), false); + free(cur_request_id); }else { uint32_t rest_pre_count = *requet_id; @@ -253,28 +257,34 @@ current_sandbox_start(void) // Copy data into pre_func_output ssize_t output_length = sandbox->request_response_data_length - sandbox->request_length; - char *pre_func_output = (char *)malloc(output_length); - if (!pre_func_output) { + char *pre_func_outputi = (char *)malloc(output_length); + if (!pre_func_outputi) { fprintf(stderr, "Failed to allocate memory for the previous output: %s\n", strerror(errno)); goto err; } - memcpy(pre_func_output, sandbox->request_response_data + sandbox->request_length, output_length); + memcpy(pre_func_outputi, sandbox->request_response_data + sandbox->request_length, output_length); uint64_t enqueue_timestamp = __getcycles(); - + const char *previous_output = sandbox_request->previous_function_output ? sandbox_request->previous_function_output : ""; ssize_t new_output_length = sandbox_request->output_length + output_length + 2; char *new_output = (char *)malloc(new_output_length); if (!new_output) { fprintf(stderr, "Failed to allocate memory for the new output: %s\n", strerror(errno)); - free(pre_func_output); + free(pre_func_outputi); goto err; } - snprintf(new_output, new_output_length, "%s&%s", previous_output, pre_func_output); - free(sandbox_request->previous_function_output); - sandbox_request->previous_function_output = NULL; + memset(new_output, 0, new_output_length); + snprintf(new_output, new_output_length, "%s&%s", previous_output, pre_func_outputi); + if(sandbox_request->previous_function_output != NULL) + { + free(sandbox_request->previous_function_output); + sandbox_request->previous_function_output = NULL; + } + assert(new_output); sandbox_request->previous_function_output = new_output; - free(pre_func_output); + free(pre_func_outputi); + pre_func_outputi = NULL; sandbox_request->output_length = new_output_length; rest_pre_count --; @@ -283,21 +293,24 @@ current_sandbox_start(void) map_upsert(sandbox_request_id, cur_request_id, strlen(cur_request_id), &rest_pre_count, sizeof(uint32_t)); }else { + uint64_t enqueue_timestamp = __getcycles(); + sandbox_request->enqueue_timestamp = enqueue_timestamp; global_request_scheduler_add(sandbox_request); map_delete(sandbox_req_map, cur_request_id, strlen(cur_request_id)); map_delete(sandbox_request_id, cur_request_id, strlen(cur_request_id)); - } + } + free(cur_request_id); } if (sandbox->request_from_outside) { sandbox_remove_from_epoll(sandbox); } sandbox_set_as_returned(sandbox, SANDBOX_RUNNING); - } - else + }else { error_message = "the strcuture of DAG is not supported\n"; goto err; - } + } + pthread_mutex_unlock(&lock); } else { /* Retrieve the result, construct the HTTP response, and send to client */ if (sandbox_send_response(sandbox) < 0) { diff --git a/runtime/src/module.c b/runtime/src/module.c index 5ff6400..7862b9b 100644 --- a/runtime/src/module.c +++ b/runtime/src/module.c @@ -20,7 +20,6 @@ const int JSON_MAX_ELEMENT_COUNT = 16; const int JSON_MAX_ELEMENT_SIZE = 1024; const int PRE_MODULE_COUNT = 4; -struct module **nodes; /************************* * Private Static Inline * @@ -377,9 +376,9 @@ module_new_from_json(char *file_name) char *request_headers = NULL; char *reponse_headers = NULL; //struct module *tail_module = NULL; - nodes = malloc(JSON_MAX_ELEMENT_COUNT * sizeof(struct module*)); + struct module **nodes = malloc(JSON_MAX_ELEMENT_COUNT * sizeof(struct module*)); if (nodes == NULL) { - fprintf(stderr, "Memory allocation failed for nodes array\n"); + panic("Memory allocation failed for nodes array\n"); } for (int i = 0; i < total_tokens; i++) { assert(tokens[i].type == JSMN_OBJECT); @@ -625,24 +624,24 @@ module_new_from_json(char *file_name) free(request_headers); free(reponse_headers); for (int i = 0; i < next_module_count; i++) { - free(next_module_names[i]); // 释放每个字符串的内存 + free(next_module_names[i]); } - free(next_module_names); // 最后释放指针数组的内存 + free(next_module_names); } if (module_count == 0) panic("%s contained no active modules\n", file_name); - for (ssize_t i = 0; i < module_count; i++) { + for (int i = 0; i < module_count; i++) { assert(nodes[i]); - ssize_t count = nodes[i]->next_module_count; + uint32_t count = nodes[i]->next_module_count; if (count == 0) continue; nodes[i]->next_module = (struct module**) malloc(count * sizeof(struct module*)); if (nodes[i]->next_module == NULL) panic("Failed to allocate memory for next_module"); - for (size_t j = 0; j < count; j++) { - for (size_t m = i + 1; m < module_count; m++) { - if (strcmp(nodes[i]->next_module_names[j], nodes[m]->name) == 0) { + for (int j = 0; j < count; j++) { + for (int m = i + 1; m < module_count; m++) { + if (strncmp(nodes[i]->next_module_names[j], nodes[m]->name, MODULE_MAX_NAME_LENGTH) == 0) { assert(nodes[m]); uint32_t precount = nodes[m]->pre_module_count; if (nodes[m]->pre_module == NULL) { @@ -661,7 +660,7 @@ module_new_from_json(char *file_name) } } } - //free(nodes); + free(nodes); #ifdef LOG_MODULE_LOADING debuglog("Loaded %d module%s!\n", module_count, module_count > 1 ? "s" : ""); #endif diff --git a/runtime_sandbox_perf_log.log b/runtime_sandbox_perf_log.log index e69de29..45c6c7a 100644 --- a/runtime_sandbox_perf_log.log +++ b/runtime_sandbox_perf_log.log @@ -0,0 +1 @@ +threadid,id,function,state,deadline,actual,queued,initializing,runnable,running,blocked,returned,memory diff --git a/sledge.log b/sledge.log index d9722e0..667d306 100755 --- a/sledge.log +++ b/sledge.log @@ -26,3 +26,4 @@ C: 01, T: 0x7ffff7bfdd80, F: module_new> Stack Size: 524288 C: 01, T: 0x7ffff7bfdd80, F: module_new> Stack Size: 524288 +double free or corruption (fasttop)