From 9ca10b2413b993646f32aaa39165e786c335cc59 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Mon, 7 Mar 2022 18:47:28 -0500 Subject: [PATCH] Rework node slab garbage collection to limit blocking work threads Also remove debug mode from forcing foreground mode --- libfuse/lib/fmp.h | 92 ++++++++++++++++++++++++++------------------ libfuse/lib/fuse.c | 79 ++++++++++++++++++++----------------- libfuse/lib/helper.c | 2 - 3 files changed, 98 insertions(+), 75 deletions(-) diff --git a/libfuse/lib/fmp.h b/libfuse/lib/fmp.h index e1131e37..ee07e30e 100644 --- a/libfuse/lib/fmp.h +++ b/libfuse/lib/fmp.h @@ -249,6 +249,14 @@ fmp_avail_objs(fmp_t *fmp_) return fmp_->avail_objs; } +static +inline +uint64_t +fmp_objs_per_slab(fmp_t *fmp_) +{ + return (fmp_->slab_size / fmp_->obj_size); +} + static inline uint64_t @@ -256,15 +264,19 @@ fmp_objs_in_slab(fmp_t *fmp_, void *slab_) { char *slab; + uint64_t objs_per_slab; uint64_t objs_in_slab; - objs_in_slab = 0; - slab = (char*)slab_; + slab = (char*)slab_; + objs_in_slab = 0; + objs_per_slab = fmp_objs_per_slab(fmp_); for(mem_stack_t *stack = fmp_->objs; stack != NULL; stack = stack->next) { char *obj = (char*)stack; if((obj >= slab) && (obj < (slab + fmp_->slab_size))) objs_in_slab++; + if(objs_in_slab >= objs_per_slab) + break; } return objs_in_slab; @@ -276,17 +288,27 @@ void fmp_remove_objs_in_slab(fmp_t *fmp_, void *slab_) { - char *slab = (char*)slab_; - mem_stack_t **p = &fmp_->objs; + char *slab; + uint64_t objs_per_slab; + uint64_t objs_in_slab; + mem_stack_t **p; + p = &fmp_->objs; + slab = (char*)slab_; + objs_in_slab = 0; + objs_per_slab = fmp_objs_per_slab(fmp_); while((*p) != NULL) { char *obj = (char*)*p; if((obj >= slab) && (obj < (slab + fmp_->slab_size))) { + objs_in_slab++; *p = (*p)->next; fmp_->avail_objs--; + + if(objs_in_slab >= objs_per_slab) + break; continue; } @@ -297,47 +319,40 @@ fmp_remove_objs_in_slab(fmp_t *fmp_, static inline int -fmp_gc(fmp_t *fmp_) +fmp_gc_slab(fmp_t *fmp_, + uint64_t slab_idx_) { - int i; - int freed_slabs; + char *slab; + uint64_t objs_in_slab; uint64_t objs_per_slab; - objs_per_slab = (fmp_->slab_size / fmp_->obj_size); + slab_idx_ = (slab_idx_ % kv_size(fmp_->slabs)); - i = 0; - freed_slabs = 0; - while(i < kv_size(fmp_->slabs)) - { - char *slab; - uint64_t objs_in_slab; + slab = kv_A(fmp_->slabs,slab_idx_); - slab = kv_A(fmp_->slabs,i); + objs_per_slab = fmp_objs_per_slab(fmp_); + objs_in_slab = fmp_objs_in_slab(fmp_,slab); + if(objs_in_slab != objs_per_slab) + return 0; - objs_in_slab = fmp_objs_in_slab(fmp_,slab); - if(objs_in_slab != objs_per_slab) - { - i++; - continue; - } + fmp_remove_objs_in_slab(fmp_,slab); + kv_delete(fmp_->slabs,slab_idx_); + fmp_slab_free_mmap(fmp_,slab); - fmp_remove_objs_in_slab(fmp_,slab); - - kv_delete(fmp_->slabs,i); - - fmp_slab_free_mmap(fmp_,slab); - freed_slabs++; - } - - return freed_slabs; + return 1; } + static inline -uint64_t -fmp_objs_per_slab(fmp_t *fmp_) +int +fmp_gc(fmp_t *fmp_) { - return (fmp_->slab_size / fmp_->obj_size); + uint64_t slab_idx; + + slab_idx = rand(); + + return fmp_gc_slab(fmp_,slab_idx); } static @@ -345,14 +360,15 @@ inline double fmp_slab_usage_ratio(fmp_t *fmp_) { - double rv; - uint64_t objs_per_slab; + double avail_objs; + double objs_per_slab; + double nums_of_slabs; + avail_objs = fmp_->avail_objs; objs_per_slab = fmp_objs_per_slab(fmp_); + nums_of_slabs = kv_size(fmp_->slabs); - rv = ((double)fmp_->avail_objs / (double)objs_per_slab); - - return rv; + return (avail_objs / (objs_per_slab * nums_of_slabs)); } static diff --git a/libfuse/lib/fuse.c b/libfuse/lib/fuse.c index 49a60ab5..d2f7c1fa 100644 --- a/libfuse/lib/fuse.c +++ b/libfuse/lib/fuse.c @@ -62,6 +62,7 @@ struct fuse_config unsigned int umask; int remember; int debug; + int nogc; int use_ino; int set_mode; int set_uid; @@ -3903,6 +3904,7 @@ static const struct fuse_opt fuse_lib_opts[] = FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), FUSE_LIB_OPT("debug", debug,1), FUSE_LIB_OPT("-d", debug,1), + FUSE_LIB_OPT("nogc", nogc,1), FUSE_LIB_OPT("umask=", set_mode,1), FUSE_LIB_OPT("umask=%o", umask,0), FUSE_LIB_OPT("uid=", set_uid,1), @@ -4002,38 +4004,40 @@ void metrics_log_nodes_info(struct fuse *f_, FILE *file_) { + char buf[1024]; + pthread_mutex_lock(&f_->lock); - - fprintf(file_, - "time: %zu\n" - "sizeof(node): %zu\n" - "node id_table size: %zu\n" - "node id_table usage: %zu\n" - "node id_table total allocated memory: %zu\n" - "node name_table size: %zu\n" - "node name_table usage: %zu\n" - "node name_table total allocated memory: %zu\n" - "node memory pool slab count: %zu\n" - "node memory pool usage ratio: %f\n" - "node memory pool avail objs: %zu\n" - "node memory pool total allocated memory: %zu\n" - "\n" - , - time(NULL), - sizeof(struct node), - f_->id_table.size, - f_->id_table.use, - (f_->id_table.size * sizeof(struct node*)), - f_->name_table.size, - f_->name_table.use, - (f_->name_table.size * sizeof(struct node*)), - lfmp_slab_count(&f_->node_fmp), - lfmp_slab_usage_ratio(&f_->node_fmp), - lfmp_avail_objs(&f_->node_fmp), - lfmp_total_allocated_memory(&f_->node_fmp) - ); - + snprintf(buf,sizeof(buf), + "time: %zu\n" + "sizeof(node): %zu\n" + "node id_table size: %zu\n" + "node id_table usage: %zu\n" + "node id_table total allocated memory: %zu\n" + "node name_table size: %zu\n" + "node name_table usage: %zu\n" + "node name_table total allocated memory: %zu\n" + "node memory pool slab count: %zu\n" + "node memory pool usage ratio: %f\n" + "node memory pool avail objs: %zu\n" + "node memory pool total allocated memory: %zu\n" + "\n" + , + time(NULL), + sizeof(struct node), + f_->id_table.size, + f_->id_table.use, + (f_->id_table.size * sizeof(struct node*)), + f_->name_table.size, + f_->name_table.use, + (f_->name_table.size * sizeof(struct node*)), + lfmp_slab_count(&f_->node_fmp), + lfmp_slab_usage_ratio(&f_->node_fmp), + lfmp_avail_objs(&f_->node_fmp), + lfmp_total_allocated_memory(&f_->node_fmp) + ); pthread_mutex_unlock(&f_->lock); + + fputs(buf,file_); } static @@ -4068,11 +4072,13 @@ static void* fuse_maintenance_loop(void *fuse_) { + int gc; int loops; int sleep_time; double slab_usage_ratio; struct fuse *f = (struct fuse*)fuse_; + gc = 0; loops = 0; sleep_time = 60; while(1) @@ -4080,12 +4086,15 @@ fuse_maintenance_loop(void *fuse_) if(remember_nodes(f)) fuse_prune_remembered_nodes(f); - slab_usage_ratio = lfmp_slab_usage_ratio(&f->node_fmp); - if(slab_usage_ratio > 3.0) - lfmp_gc(&f->node_fmp); + if((loops % 15) == 0) + { + fuse_malloc_trim(); + gc = 1; + } - if(loops % 15) - fuse_malloc_trim(); + // Trigger a followup gc if this gc succeeds + if(!f->conf.nogc && gc) + gc = lfmp_gc(&f->node_fmp); if(g_LOG_METRICS) metrics_log_nodes_info_to_tmp_dir(f); diff --git a/libfuse/lib/helper.c b/libfuse/lib/helper.c index 949b9d09..8dd48ad2 100644 --- a/libfuse/lib/helper.c +++ b/libfuse/lib/helper.c @@ -40,8 +40,6 @@ static const struct fuse_opt fuse_helper_opts[] = { - FUSE_HELPER_OPT("-d", foreground), - FUSE_HELPER_OPT("debug", foreground), FUSE_HELPER_OPT("-f", foreground), FUSE_HELPER_OPT("fsname=", nodefault_subtype), FUSE_HELPER_OPT("subtype=", nodefault_subtype),