summaryrefslogtreecommitdiffstats
path: root/libnetdata
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@netdata.cloud>2023-01-20 00:50:42 +0200
committerGitHub <noreply@github.com>2023-01-20 00:50:42 +0200
commit9232bfb6a072155388578dc4e1338c6002afb515 (patch)
treedc85f9bfe3ed97394e6f2a92a2f710796d6d8979 /libnetdata
parent86538b005de50f23c9ff66542abab11683b85c06 (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.c12
-rw-r--r--libnetdata/buffer/buffer.c60
-rw-r--r--libnetdata/buffer/buffer.h3
-rw-r--r--libnetdata/circular_buffer/circular_buffer.c30
-rw-r--r--libnetdata/circular_buffer/circular_buffer.h3
-rw-r--r--libnetdata/dictionary/dictionary.c6
-rw-r--r--libnetdata/dictionary/dictionary.h2
-rw-r--r--libnetdata/eval/eval.c4
-rw-r--r--libnetdata/json/json.c2
-rw-r--r--libnetdata/libnetdata.h2
-rw-r--r--libnetdata/onewayalloc/onewayalloc.c13
-rw-r--r--libnetdata/onewayalloc/onewayalloc.h2
-rw-r--r--libnetdata/string/string.c35
-rw-r--r--libnetdata/worker_utilization/worker_utilization.c19
-rw-r--r--libnetdata/worker_utilization/worker_utilization.h1
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);