为hash表添加锁

newsch
hwwang 4 months ago
parent 0b1fb6c5d7
commit 702f5de60d

@ -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,

@ -0,0 +1 @@
10

@ -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

@ -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

@ -4,10 +4,18 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#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);
}
free(prev);
did_delete = true;
goto DONE;
}
for (struct map_node *node = prev->next; node != NULL; prev = node, node = node->next) {
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);
}
free(node);
did_delete = true;
goto DONE;
break;
}
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);
}*/

@ -3,12 +3,12 @@
#include <stdlib.h>
#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;
}

@ -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,12 +257,12 @@ 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();
@ -267,14 +271,20 @@ current_sandbox_start(void)
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);
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) {

@ -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

@ -0,0 +1 @@
threadid,id,function,state,deadline,actual,queued,initializing,runnable,running,blocked,returned,memory

@ -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)

Loading…
Cancel
Save