diff options
author | Costa Tsaousis <costa@netdata.cloud> | 2023-01-20 00:50:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-20 00:50:42 +0200 |
commit | 9232bfb6a072155388578dc4e1338c6002afb515 (patch) | |
tree | dc85f9bfe3ed97394e6f2a92a2f710796d6d8979 /libnetdata | |
parent | 86538b005de50f23c9ff66542abab11683b85c06 (diff) |
track memory footprint of Netdata (#14294)
* track memory footprint of Netdata
* track db modes alloc/ram/save/map
* track system info; track sender and receiver
* fixes
* more fixes
* track workers memory, onewayalloc memory; unify judyhs size estimation
* track replication structures and buffers
* Properly clear host RRDHOST_FLAG_METADATA_UPDATE flag
* flush the replication buffer every 1000 times the circular buffer is found empty
* dont take timestamp too frequently in sender loop
* sender buffers are not used by the same thread as the sender, so they were never recreated - fixed it
* free sender thread buffer on replication threads when replication is idle
* use the last sender flag as a timestamp of the last buffer recreation
* free cbuffer before reconnecting
* recreate cbuffer on every flush
* timings for journal v2 loading
* inlining of metric and cache functions
* aral likely/unlikely
* free left-over thread buffers
* fix NULL pointer dereference in replication
* free sender thread buffer on sender thread too
* mark ctx as used before flushing
* better logging on ctx datafiles closing
Co-authored-by: Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com>
Diffstat (limited to 'libnetdata')
-rw-r--r-- | libnetdata/arrayalloc/arrayalloc.c | 12 | ||||
-rw-r--r-- | libnetdata/buffer/buffer.c | 60 | ||||
-rw-r--r-- | libnetdata/buffer/buffer.h | 3 | ||||
-rw-r--r-- | libnetdata/circular_buffer/circular_buffer.c | 30 | ||||
-rw-r--r-- | libnetdata/circular_buffer/circular_buffer.h | 3 | ||||
-rw-r--r-- | libnetdata/dictionary/dictionary.c | 6 | ||||
-rw-r--r-- | libnetdata/dictionary/dictionary.h | 2 | ||||
-rw-r--r-- | libnetdata/eval/eval.c | 4 | ||||
-rw-r--r-- | libnetdata/json/json.c | 2 | ||||
-rw-r--r-- | libnetdata/libnetdata.h | 2 | ||||
-rw-r--r-- | libnetdata/onewayalloc/onewayalloc.c | 13 | ||||
-rw-r--r-- | libnetdata/onewayalloc/onewayalloc.h | 2 | ||||
-rw-r--r-- | libnetdata/string/string.c | 35 | ||||
-rw-r--r-- | libnetdata/worker_utilization/worker_utilization.c | 19 | ||||
-rw-r--r-- | libnetdata/worker_utilization/worker_utilization.h | 1 |
15 files changed, 132 insertions, 62 deletions
diff --git a/libnetdata/arrayalloc/arrayalloc.c b/libnetdata/arrayalloc/arrayalloc.c index 090e72f363..78b271b803 100644 --- a/libnetdata/arrayalloc/arrayalloc.c +++ b/libnetdata/arrayalloc/arrayalloc.c @@ -144,10 +144,10 @@ static void arrayalloc_init(ARAL *ar) { #ifdef NETDATA_INTERNAL_CHECKS static inline void arrayalloc_free_validate_internal_check(ARAL *ar, ARAL_FREE *fr) { - if(fr->size < ar->internal.element_size) + if(unlikely(fr->size < ar->internal.element_size)) fatal("ARRAYALLOC: free item of size %zu, less than the expected element size %zu", fr->size, ar->internal.element_size); - if(fr->size % ar->internal.element_size) + if(unlikely(fr->size % ar->internal.element_size)) fatal("ARRAYALLOC: free item of size %zu is not multiple to element size %zu", fr->size, ar->internal.element_size); } #else @@ -234,13 +234,13 @@ static void arrayalloc_add_page(ARAL *ar TRACE_ALLOCATIONS_FUNCTION_DEFINITION_P arrayalloc_free_validate_internal_check(ar, fr); } -static void arrayalloc_lock(ARAL *ar) { - if(!ar->internal.lockless) +static inline void arrayalloc_lock(ARAL *ar) { + if(likely(!ar->internal.lockless)) netdata_spinlock_lock(&ar->internal.spinlock); } -static void arrayalloc_unlock(ARAL *ar) { - if(!ar->internal.lockless) +static inline void arrayalloc_unlock(ARAL *ar) { + if(likely(!ar->internal.lockless)) netdata_spinlock_unlock(&ar->internal.spinlock); } diff --git a/libnetdata/buffer/buffer.c b/libnetdata/buffer/buffer.c index d0940588fc..eeb283209f 100644 --- a/libnetdata/buffer/buffer.c +++ b/libnetdata/buffer/buffer.c @@ -442,28 +442,28 @@ void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minute buffer_need_bytes(wb, 36); char *b = &wb->buffer[wb->len]; - char *p = b; - - *p++ = '0' + year / 1000; year %= 1000; - *p++ = '0' + year / 100; year %= 100; - *p++ = '0' + year / 10; - *p++ = '0' + year % 10; - *p++ = '-'; - *p++ = '0' + month / 10; - *p++ = '0' + month % 10; - *p++ = '-'; - *p++ = '0' + day / 10; - *p++ = '0' + day % 10; - *p++ = ' '; - *p++ = '0' + hours / 10; - *p++ = '0' + hours % 10; - *p++ = ':'; - *p++ = '0' + minutes / 10; - *p++ = '0' + minutes % 10; - *p++ = ':'; - *p++ = '0' + seconds / 10; - *p++ = '0' + seconds % 10; - *p = '\0'; + char *p = b; + + *p++ = '0' + year / 1000; year %= 1000; + *p++ = '0' + year / 100; year %= 100; + *p++ = '0' + year / 10; + *p++ = '0' + year % 10; + *p++ = '-'; + *p++ = '0' + month / 10; + *p++ = '0' + month % 10; + *p++ = '-'; + *p++ = '0' + day / 10; + *p++ = '0' + day % 10; + *p++ = ' '; + *p++ = '0' + hours / 10; + *p++ = '0' + hours % 10; + *p++ = ':'; + *p++ = '0' + minutes / 10; + *p++ = '0' + minutes % 10; + *p++ = ':'; + *p++ = '0' + seconds / 10; + *p++ = '0' + seconds % 10; + *p = '\0'; wb->len += (size_t)(p - b); @@ -472,7 +472,7 @@ void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minute buffer_overflow_check(wb); } -BUFFER *buffer_create(size_t size) +BUFFER *buffer_create(size_t size, size_t *statistics) { BUFFER *b; @@ -483,9 +483,13 @@ BUFFER *buffer_create(size_t size) b->buffer[0] = '\0'; b->size = size; b->contenttype = CT_TEXT_PLAIN; + b->statistics = statistics; buffer_overflow_init(b); buffer_overflow_check(b); + if(b->statistics) + __atomic_add_fetch(b->statistics, b->size + sizeof(BUFFER) + sizeof(BUFFER_OVERFLOW_EOF) + 2, __ATOMIC_RELAXED); + return(b); } @@ -496,6 +500,9 @@ void buffer_free(BUFFER *b) { debug(D_WEB_BUFFER, "Freeing web buffer of size %zu.", b->size); + if(b->statistics) + __atomic_sub_fetch(b->statistics, b->size + sizeof(BUFFER) + sizeof(BUFFER_OVERFLOW_EOF) + 2, __ATOMIC_RELAXED); + freez(b->buffer); freez(b); } @@ -510,9 +517,7 @@ void buffer_increase(BUFFER *b, size_t free_size_required) { size_t minimum = WEB_DATA_LENGTH_INCREASE_STEP; if(minimum > wanted) wanted = minimum; - size_t optimal = b->size; - if(b->size > 5*1024*1024) optimal = b->size / 2; - + size_t optimal = (b->size > 5*1024*1024) ? b->size / 2 : b->size; if(optimal > wanted) wanted = optimal; debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + wanted); @@ -520,6 +525,9 @@ void buffer_increase(BUFFER *b, size_t free_size_required) { b->buffer = reallocz(b->buffer, b->size + wanted + sizeof(BUFFER_OVERFLOW_EOF) + 2); b->size += wanted; + if(b->statistics) + __atomic_add_fetch(b->statistics, wanted, __ATOMIC_RELAXED); + buffer_overflow_init(b); buffer_overflow_check(b); } diff --git a/libnetdata/buffer/buffer.h b/libnetdata/buffer/buffer.h index ce6f52899b..0fa3495b4a 100644 --- a/libnetdata/buffer/buffer.h +++ b/libnetdata/buffer/buffer.h @@ -15,6 +15,7 @@ typedef struct web_buffer { uint8_t options; // options related to the content time_t date; // the timestamp this content has been generated time_t expires; // the timestamp this content expires + size_t *statistics; } BUFFER; // options @@ -61,7 +62,7 @@ void buffer_rrd_value(BUFFER *wb, NETDATA_DOUBLE value); void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds); void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds); -BUFFER *buffer_create(size_t size); +BUFFER *buffer_create(size_t size, size_t *statistics); void buffer_free(BUFFER *b); void buffer_increase(BUFFER *b, size_t free_size_required); diff --git a/libnetdata/circular_buffer/circular_buffer.c b/libnetdata/circular_buffer/circular_buffer.c index c791b420b0..b2bded1791 100644 --- a/libnetdata/circular_buffer/circular_buffer.c +++ b/libnetdata/circular_buffer/circular_buffer.c @@ -1,16 +1,24 @@ #include "../libnetdata.h" -struct circular_buffer *cbuffer_new(size_t initial, size_t max) { - struct circular_buffer *result = mallocz(sizeof(*result)); - result->size = initial; - result->data = mallocz(initial); - result->write = 0; - result->read = 0; - result->max_size = max; - return result; +struct circular_buffer *cbuffer_new(size_t initial, size_t max, size_t *statistics) { + struct circular_buffer *buf = mallocz(sizeof(struct circular_buffer)); + buf->size = initial; + buf->data = mallocz(initial); + buf->write = 0; + buf->read = 0; + buf->max_size = max; + buf->statistics = statistics; + + if(buf->statistics) + __atomic_add_fetch(buf->statistics, sizeof(struct circular_buffer) + buf->size, __ATOMIC_RELAXED); + + return buf; } void cbuffer_free(struct circular_buffer *buf) { + if(buf && buf->statistics) + __atomic_sub_fetch(buf->statistics, sizeof(struct circular_buffer) + buf->size, __ATOMIC_RELAXED); + freez(buf->data); freez(buf); } @@ -19,6 +27,8 @@ static int cbuffer_realloc_unsafe(struct circular_buffer *buf) { // Check that we can grow if (buf->size >= buf->max_size) return 1; + + size_t old_size = buf->size; size_t new_size = buf->size * 2; if (new_size > buf->max_size) new_size = buf->max_size; @@ -43,6 +53,10 @@ static int cbuffer_realloc_unsafe(struct circular_buffer *buf) { freez(buf->data); buf->data = new_data; buf->size = new_size; + + if(buf->statistics) + __atomic_add_fetch(buf->statistics, new_size - old_size, __ATOMIC_RELAXED); + return 0; } diff --git a/libnetdata/circular_buffer/circular_buffer.h b/libnetdata/circular_buffer/circular_buffer.h index 8c42aa807f..9d29a84d70 100644 --- a/libnetdata/circular_buffer/circular_buffer.h +++ b/libnetdata/circular_buffer/circular_buffer.h @@ -5,10 +5,11 @@ struct circular_buffer { size_t size, write, read, max_size; + size_t *statistics; char *data; }; -struct circular_buffer *cbuffer_new(size_t initial, size_t max); +struct circular_buffer *cbuffer_new(size_t initial, size_t max, size_t *statistics); void cbuffer_free(struct circular_buffer *buf); int cbuffer_add_unsafe(struct circular_buffer *buf, const char *d, size_t d_len); void cbuffer_remove_unsafe(struct circular_buffer *buf, size_t num); diff --git a/libnetdata/dictionary/dictionary.c b/libnetdata/dictionary/dictionary.c index 045dbbe55b..acc509e7ce 100644 --- a/libnetdata/dictionary/dictionary.c +++ b/libnetdata/dictionary/dictionary.c @@ -260,7 +260,7 @@ static inline void pointer_del(DICTIONARY *dict __maybe_unused, DICTIONARY_ITEM static inline void DICTIONARY_STATS_PLUS_MEMORY(DICTIONARY *dict, size_t key_size, size_t item_size, size_t value_size) { if(key_size) - __atomic_fetch_add(&dict->stats->memory.indexed, (long)key_size, __ATOMIC_RELAXED); + __atomic_fetch_add(&dict->stats->memory.index, (long)JUDYHS_INDEX_SIZE_ESTIMATE(key_size), __ATOMIC_RELAXED); if(item_size) __atomic_fetch_add(&dict->stats->memory.dict, (long)item_size, __ATOMIC_RELAXED); @@ -270,7 +270,7 @@ static inline void DICTIONARY_STATS_PLUS_MEMORY(DICTIONARY *dict, size_t key_siz } static inline void DICTIONARY_STATS_MINUS_MEMORY(DICTIONARY *dict, size_t key_size, size_t item_size, size_t value_size) { if(key_size) - __atomic_fetch_sub(&dict->stats->memory.indexed, (long)key_size, __ATOMIC_RELAXED); + __atomic_fetch_sub(&dict->stats->memory.index, (long)JUDYHS_INDEX_SIZE_ESTIMATE(key_size), __ATOMIC_RELAXED); if(item_size) __atomic_fetch_sub(&dict->stats->memory.dict, (long)item_size, __ATOMIC_RELAXED); @@ -380,7 +380,7 @@ size_t dictionary_referenced_items(DICTIONARY *dict) { long int dictionary_stats_for_registry(DICTIONARY *dict) { if(unlikely(!dict)) return 0; - return (dict->stats->memory.indexed + dict->stats->memory.dict); + return (dict->stats->memory.index + dict->stats->memory.dict); } void dictionary_version_increment(DICTIONARY *dict) { __atomic_fetch_add(&dict->version, 1, __ATOMIC_SEQ_CST); diff --git a/libnetdata/dictionary/dictionary.h b/libnetdata/dictionary/dictionary.h index 0e7b3d39ff..d85cb1d1ea 100644 --- a/libnetdata/dictionary/dictionary.h +++ b/libnetdata/dictionary/dictionary.h @@ -91,7 +91,7 @@ struct dictionary_stats { // memory struct { - long indexed; // bytes of keys indexed (indication of the index size) + long index; // bytes of keys indexed (indication of the index size) long values; // bytes of caller structures long dict; // bytes of the structures dictionary needs } memory; diff --git a/libnetdata/eval/eval.c b/libnetdata/eval/eval.c index 0e429a08cb..c7570bd2f9 100644 --- a/libnetdata/eval/eval.c +++ b/libnetdata/eval/eval.c @@ -1126,7 +1126,7 @@ EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, in return NULL; } - BUFFER *out = buffer_create(1024); + BUFFER *out = buffer_create(1024, NULL); print_parsed_as_node(out, op, &err); if(err != EVAL_ERROR_OK) { error("failed to re-generate expression '%s' with reason: %s", string, expression_strerror(err)); @@ -1141,7 +1141,7 @@ EVAL_EXPRESSION *expression_parse(const char *string, const char **failed_at, in exp->parsed_as = strdupz(buffer_tostring(out)); buffer_free(out); - exp->error_msg = buffer_create(100); + exp->error_msg = buffer_create(100, NULL); exp->nodes = (void *)op; return exp; diff --git a/libnetdata/json/json.c b/libnetdata/json/json.c index d5f62edaf1..532b677ceb 100644 --- a/libnetdata/json/json.c +++ b/libnetdata/json/json.c @@ -90,7 +90,7 @@ jsmntok_t *json_tokenise(char *js, size_t len, size_t *count) */ int json_callback_print(JSON_ENTRY *e) { - BUFFER *wb=buffer_create(300); + BUFFER *wb=buffer_create(300, NULL); buffer_sprintf(wb,"%s = ", e->name); char txt[50]; diff --git a/libnetdata/libnetdata.h b/libnetdata/libnetdata.h index 56d984dec5..fa09a1e780 100644 --- a/libnetdata/libnetdata.h +++ b/libnetdata/libnetdata.h @@ -11,6 +11,8 @@ extern "C" { #include <config.h> #endif +#define JUDYHS_INDEX_SIZE_ESTIMATE(key_bytes) (((key_bytes) + sizeof(Word_t) - 1) / sizeof(Word_t) * 4) + #if defined(NETDATA_DEV_MODE) && !defined(NETDATA_INTERNAL_CHECKS) #define NETDATA_INTERNAL_CHECKS 1 #endif diff --git a/libnetdata/onewayalloc/onewayalloc.c b/libnetdata/onewayalloc/onewayalloc.c index 59c3b68598..2f007b1898 100644 --- a/libnetdata/onewayalloc/onewayalloc.c +++ b/libnetdata/onewayalloc/onewayalloc.c @@ -14,6 +14,12 @@ typedef struct owa_page { struct owa_page *last; // the last page on the list - we currently allocate on this } OWA_PAGE; +static size_t onewayalloc_total_memory = 0; + +size_t onewayalloc_allocated_memory(void) { + return __atomic_load_n(&onewayalloc_total_memory, __ATOMIC_RELAXED); +} + // allocations need to be aligned to CPU register width // https://en.wikipedia.org/wiki/Data_structure_alignment static inline size_t natural_alignment(size_t size) { @@ -60,6 +66,7 @@ static OWA_PAGE *onewayalloc_create_internal(OWA_PAGE *head, size_t size_hint) { // OWA_PAGE *page = (OWA_PAGE *)netdata_mmap(NULL, size, MAP_ANONYMOUS|MAP_PRIVATE, 0); // if(unlikely(!page)) fatal("Cannot allocate onewayalloc buffer of size %zu", size); OWA_PAGE *page = (OWA_PAGE *)mallocz(size); + __atomic_add_fetch(&onewayalloc_total_memory, size, __ATOMIC_RELAXED); page->size = size; page->offset = natural_alignment(sizeof(OWA_PAGE)); @@ -183,11 +190,17 @@ void onewayalloc_destroy(ONEWAYALLOC *owa) { // head->stats_mallocs_made, head->stats_mallocs_size, // head->stats_pages, head->stats_pages_size); + size_t total_size = 0; OWA_PAGE *page = head; while(page) { + total_size += page->size; + OWA_PAGE *p = page; page = page->next; + // munmap(p, p->size); freez(p); } + + __atomic_sub_fetch(&onewayalloc_total_memory, total_size, __ATOMIC_RELAXED); } diff --git a/libnetdata/onewayalloc/onewayalloc.h b/libnetdata/onewayalloc/onewayalloc.h index e536e0542e..a415b063b4 100644 --- a/libnetdata/onewayalloc/onewayalloc.h +++ b/libnetdata/onewayalloc/onewayalloc.h @@ -16,4 +16,6 @@ void onewayalloc_freez(ONEWAYALLOC *owa, const void *ptr); void *onewayalloc_doublesize(ONEWAYALLOC *owa, const void *src, size_t oldsize); +size_t onewayalloc_allocated_memory(void); + #endif // ONEWAYALLOC_H diff --git a/libnetdata/string/string.c b/libnetdata/string/string.c index d2db8aab43..4e232523c8 100644 --- a/libnetdata/string/string.c +++ b/libnetdata/string/string.c @@ -56,14 +56,29 @@ static struct string_hashtable { #define string_stats_atomic_decrement(var) __atomic_sub_fetch(&string_base.var, 1, __ATOMIC_RELAXED) void string_statistics(size_t *inserts, size_t *deletes, size_t *searches, size_t *entries, size_t *references, size_t *memory, size_t *duplications, size_t *releases) { - *inserts = string_base.inserts; - *deletes = string_base.deletes; - *searches = string_base.searches; - *entries = (size_t)string_base.entries; - *references = (size_t)string_base.active_references; - *memory = (size_t)string_base.memory; - *duplications = string_base.duplications; - *releases = string_base.releases; + if(inserts) + *inserts = string_base.inserts; + + if(deletes) + *deletes = string_base.deletes; + + if(searches) + *searches = string_base.searches; + + if(entries) + *entries = (size_t)string_base.entries; + + if(references) + *references = (size_t)string_base.active_references; + + if(memory) + *memory = (size_t)string_base.memory; + + if(duplications) + *duplications = string_base.duplications; + + if(releases) + *releases = string_base.releases; } #define string_entry_acquire(se) __atomic_add_fetch(&((se)->refcount), 1, __ATOMIC_SEQ_CST); @@ -186,7 +201,7 @@ static inline STRING *string_index_insert(const char *str, size_t length) { *ptr = string; string_base.inserts++; string_base.entries++; - string_base.memory += (long)mem_size; + string_base.memory += (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(length)); } else { // the item is already in the index @@ -240,7 +255,7 @@ static inline void string_index_delete(STRING *string) { size_t mem_size = sizeof(STRING) + string->length; string_base.deletes++; string_base.entries--; - string_base.memory -= (long)mem_size; + string_base.memory -= (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(string->length)); freez(string); } diff --git a/libnetdata/worker_utilization/worker_utilization.c b/libnetdata/worker_utilization/worker_utilization.c index b0dcf034dd..867cd266c6 100644 --- a/libnetdata/worker_utilization/worker_utilization.c +++ b/libnetdata/worker_utilization/worker_utilization.c @@ -52,6 +52,7 @@ struct workers_workname { // this is what we add to Ju static struct workers_globals { SPINLOCK spinlock; Pvoid_t worknames_JudyHS; + size_t memory; } workers_globals = { // workers globals, the base of all worknames .spinlock = NETDATA_SPINLOCK_INITIALIZER, // a lock for the worknames index @@ -60,6 +61,14 @@ static struct workers_globals { static __thread struct worker *worker = NULL; // the current thread worker +size_t workers_allocated_memory(void) { + netdata_spinlock_lock(&workers_globals.spinlock); + size_t memory = workers_globals.memory; + netdata_spinlock_unlock(&workers_globals.spinlock); + + return memory; +} + void worker_register(const char *name) { if(unlikely(worker)) return; @@ -76,9 +85,9 @@ void worker_register(const char *name) { size_t name_size = strlen(name) + 1; netdata_spinlock_lock(&workers_globals.spinlock); - Pvoid_t *PValue = JudyHSGet(workers_globals.worknames_JudyHS, (void *)name, name_size); - if(!PValue) - PValue = JudyHSIns(&workers_globals.worknames_JudyHS, (void *)name, name_size, PJE0); + workers_globals.memory += sizeof(struct worker) + strlen(worker->tag) + 1 + strlen(worker->workname) + 1; + + Pvoid_t *PValue = JudyHSIns(&workers_globals.worknames_JudyHS, (void *)name, name_size, PJE0); struct workers_workname *workname = *PValue; if(!workname) { @@ -86,6 +95,8 @@ void worker_register(const char *name) { netdata_spinlock_init(&workname->spinlock); workname->base = NULL; *PValue = workname; + + workers_globals.memory += sizeof(struct workers_workname) + JUDYHS_INDEX_SIZE_ESTIMATE(name_size); } netdata_spinlock_lock(&workname->spinlock); @@ -136,8 +147,10 @@ void worker_unregister(void) { if(!workname->base) { JudyHSDel(&workers_globals.worknames_JudyHS, (void *) worker->workname, workname_size, PJE0); freez(workname); + workers_globals.memory -= sizeof(struct workers_workname) + JUDYHS_INDEX_SIZE_ESTIMATE(workname_size); } } + workers_globals.memory -= sizeof(struct worker) + strlen(worker->tag) + 1 + strlen(worker->workname) + 1; netdata_spinlock_unlock(&workers_globals.spinlock); for(int i = 0; i < WORKER_UTILIZATION_MAX_JOB_TYPES ;i++) { diff --git a/libnetdata/worker_utilization/worker_utilization.h b/libnetdata/worker_utilization/worker_utilization.h index f1412e6b49..6745a010bc 100644 --- a/libnetdata/worker_utilization/worker_utilization.h +++ b/libnetdata/worker_utilization/worker_utilization.h @@ -15,6 +15,7 @@ typedef enum { WORKER_METRIC_INCREMENTAL_TOTAL = 4, } WORKER_METRIC_TYPE; +size_t workers_allocated_memory(void); void worker_register(const char *name); void worker_register_job_name(size_t job_id, const char *name); void worker_register_job_custom_metric(size_t job_id, const char *name, const char *units, WORKER_METRIC_TYPE type); |