summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@netdata.cloud>2022-05-03 00:31:19 +0300
committerGitHub <noreply@github.com>2022-05-03 00:31:19 +0300
commit87c0cc2d6049c46f38b9c866668a0a24a3e962c0 (patch)
tree066c18bc90894e89ce46dc0b2e104c61018e830c /web
parent47fa3d708902fb001b2e88e4145d2a451549cd8e (diff)
One way allocator to double the speed of parallel context queries (#12787)
* one way allocator to speed up context queries * fixed a bug while expanding memory pages * reworked for clarity and finally fixed the bug of allocating memory beyond the page size * further optimize allocation step to minimize the number of allocations made * implement strdup with memcpy instead of strcpy * added documentation * prevent an uninitialized use of owa * added callocz() interface * integrate onewayalloc everywhere - apart sql queries * one way allocator is now used in context queries using archived charts in sql * align on the size of pointers * forgotten freez() * removed not needed memcpys * give unique names to global variables to avoid conflicts with system definitions
Diffstat (limited to 'web')
-rw-r--r--web/api/formatters/rrd2json.c75
-rw-r--r--web/api/formatters/rrd2json.h9
-rw-r--r--web/api/queries/query.c25
-rw-r--r--web/api/queries/rrdr.c24
-rw-r--r--web/api/queries/rrdr.h5
-rw-r--r--web/api/web_api_v1.c18
6 files changed, 85 insertions, 71 deletions
diff --git a/web/api/formatters/rrd2json.c b/web/api/formatters/rrd2json.c
index 1a8b07c7c8..9ac54f7589 100644
--- a/web/api/formatters/rrd2json.c
+++ b/web/api/formatters/rrd2json.c
@@ -2,27 +2,27 @@
#include "web/api/web_api_v1.h"
-static inline void free_single_rrdrim(RRDDIM *temp_rd, int archive_mode)
+static inline void free_single_rrdrim(ONEWAYALLOC *owa, RRDDIM *temp_rd, int archive_mode)
{
if (unlikely(!temp_rd))
return;
- freez((char *)temp_rd->id);
- freez((char *)temp_rd->name);
+ onewayalloc_freez(owa, (char *)temp_rd->id);
if (unlikely(archive_mode)) {
temp_rd->rrdset->counter--;
if (!temp_rd->rrdset->counter) {
- freez((char *)temp_rd->rrdset->name);
- freez(temp_rd->rrdset->context);
- freez(temp_rd->rrdset);
+ onewayalloc_freez(owa, (char *)temp_rd->rrdset->name);
+ onewayalloc_freez(owa, temp_rd->rrdset->context);
+ onewayalloc_freez(owa, temp_rd->rrdset);
}
}
- freez(temp_rd->state);
- freez(temp_rd);
+
+ onewayalloc_freez(owa, temp_rd->state);
+ onewayalloc_freez(owa, temp_rd);
}
-static inline void free_rrddim_list(RRDDIM *temp_rd, int archive_mode)
+static inline void free_rrddim_list(ONEWAYALLOC *owa, RRDDIM *temp_rd, int archive_mode)
{
if (unlikely(!temp_rd))
return;
@@ -30,22 +30,22 @@ static inline void free_rrddim_list(RRDDIM *temp_rd, int archive_mode)
RRDDIM *t;
while (temp_rd) {
t = temp_rd->next;
- free_single_rrdrim(temp_rd, archive_mode);
+ free_single_rrdrim(owa, temp_rd, archive_mode);
temp_rd = t;
}
}
-void free_context_param_list(struct context_param **param_list)
+void free_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list)
{
if (unlikely(!param_list || !*param_list))
return;
- free_rrddim_list(((*param_list)->rd), (*param_list)->flags & CONTEXT_FLAGS_ARCHIVE);
- freez((*param_list));
+ free_rrddim_list(owa, ((*param_list)->rd), (*param_list)->flags & CONTEXT_FLAGS_ARCHIVE);
+ onewayalloc_freez(owa, (*param_list));
*param_list = NULL;
}
-void rebuild_context_param_list(struct context_param *context_param_list, time_t after_requested)
+void rebuild_context_param_list(ONEWAYALLOC *owa, struct context_param *context_param_list, time_t after_requested)
{
RRDDIM *temp_rd = context_param_list->rd;
RRDDIM *new_rd_list = NULL, *t;
@@ -59,19 +59,19 @@ void rebuild_context_param_list(struct context_param *context_param_list, time_t
temp_rd->next = new_rd_list;
new_rd_list = temp_rd;
} else
- free_single_rrdrim(temp_rd, is_archived);
+ free_single_rrdrim(owa, temp_rd, is_archived);
temp_rd = t;
}
context_param_list->rd = new_rd_list;
};
-void build_context_param_list(struct context_param **param_list, RRDSET *st)
+void build_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list, RRDSET *st)
{
if (unlikely(!param_list || !st))
return;
if (unlikely(!(*param_list))) {
- *param_list = mallocz(sizeof(struct context_param));
+ *param_list = onewayalloc_mallocz(owa, sizeof(struct context_param));
(*param_list)->first_entry_t = LONG_MAX;
(*param_list)->last_entry_t = 0;
(*param_list)->flags = CONTEXT_FLAGS_CONTEXT;
@@ -86,14 +86,10 @@ void build_context_param_list(struct context_param **param_list, RRDSET *st)
(*param_list)->last_entry_t = MAX((*param_list)->last_entry_t, rrdset_last_entry_t_nolock(st));
rrddim_foreach_read(rd1, st) {
- RRDDIM *rd = mallocz(rd1->memsize);
- memcpy(rd, rd1, rd1->memsize);
- rd->id = strdupz(rd1->id);
- rd->name = strdupz(rd1->name);
- rd->state = mallocz(sizeof(*rd->state));
- memcpy(rd->state, rd1->state, sizeof(*rd->state));
- memcpy(&rd->state->collect_ops, &rd1->state->collect_ops, sizeof(struct rrddim_collect_ops));
- memcpy(&rd->state->query_ops, &rd1->state->query_ops, sizeof(struct rrddim_query_ops));
+ RRDDIM *rd = onewayalloc_memdupz(owa, rd1, rd1->memsize);
+ rd->id = onewayalloc_strdupz(owa, rd1->id);
+ rd->name = onewayalloc_strdupz(owa, rd1->name);
+ rd->state = onewayalloc_memdupz(owa, rd1->state, sizeof(*rd->state));
rd->next = (*param_list)->rd;
(*param_list)->rd = rd;
}
@@ -169,22 +165,27 @@ int rrdset2value_api_v1(
, int *value_is_null
, int timeout
) {
+ int ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
+
+ ONEWAYALLOC *owa = onewayalloc_create(0);
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions, NULL, timeout);
+ RRDR *r = rrd2rrdr(owa, st, points, after, before, group_method, group_time, options, dimensions, NULL, timeout);
if(!r) {
if(value_is_null) *value_is_null = 1;
- return HTTP_RESP_INTERNAL_SERVER_ERROR;
+ ret = HTTP_RESP_INTERNAL_SERVER_ERROR;
+ goto cleanup;
}
if(rrdr_rows(r) == 0) {
- rrdr_free(r);
+ rrdr_free(owa, r);
if(db_after) *db_after = 0;
if(db_before) *db_before = 0;
if(value_is_null) *value_is_null = 1;
- return HTTP_RESP_BAD_REQUEST;
+ ret = HTTP_RESP_BAD_REQUEST;
+ goto cleanup;
}
if(wb) {
@@ -199,13 +200,17 @@ int rrdset2value_api_v1(
long i = (!(options & RRDR_OPTION_REVERSED))?rrdr_rows(r) - 1:0;
*n = rrdr2value(r, i, options, value_is_null, NULL);
+ ret = HTTP_RESP_OK;
- rrdr_free(r);
- return HTTP_RESP_OK;
+cleanup:
+ if(r) rrdr_free(owa, r);
+ onewayalloc_destroy(owa);
+ return ret;
}
int rrdset2anything_api_v1(
- RRDSET *st
+ ONEWAYALLOC *owa
+ , RRDSET *st
, BUFFER *wb
, BUFFER *dimensions
, uint32_t format
@@ -225,14 +230,14 @@ int rrdset2anything_api_v1(
if (context_param_list && !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE))
st->last_accessed_time = now_realtime_sec();
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL, context_param_list, timeout);
+ RRDR *r = rrd2rrdr(owa, st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL, context_param_list, timeout);
if(!r) {
buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
return HTTP_RESP_INTERNAL_SERVER_ERROR;
}
if (r->result_options & RRDR_RESULT_OPTION_CANCEL) {
- rrdr_free(r);
+ rrdr_free(owa, r);
return HTTP_RESP_BACKEND_FETCH_FAILED;
}
@@ -411,6 +416,6 @@ int rrdset2anything_api_v1(
break;
}
- rrdr_free(r);
+ rrdr_free(owa, r);
return HTTP_RESP_OK;
}
diff --git a/web/api/formatters/rrd2json.h b/web/api/formatters/rrd2json.h
index af809c54f9..a3fe50cbbb 100644
--- a/web/api/formatters/rrd2json.h
+++ b/web/api/formatters/rrd2json.h
@@ -54,7 +54,8 @@ extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
extern void rrdr_buffer_print_format(BUFFER *wb, uint32_t format);
extern int rrdset2anything_api_v1(
- RRDSET *st
+ ONEWAYALLOC *owa
+ , RRDSET *st
, BUFFER *wb
, BUFFER *dimensions
, uint32_t format
@@ -88,8 +89,8 @@ extern int rrdset2value_api_v1(
, int timeout
);
-extern void build_context_param_list(struct context_param **param_list, RRDSET *st);
-extern void rebuild_context_param_list(struct context_param *context_param_list, time_t after_requested);
-extern void free_context_param_list(struct context_param **param_list);
+extern void build_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list, RRDSET *st);
+extern void rebuild_context_param_list(ONEWAYALLOC *owa, struct context_param *context_param_list, time_t after_requested);
+extern void free_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list);
#endif /* NETDATA_RRD2JSON_H */
diff --git a/web/api/queries/query.c b/web/api/queries/query.c
index c55a970609..9308d10bf5 100644
--- a/web/api/queries/query.c
+++ b/web/api/queries/query.c
@@ -831,7 +831,8 @@ static int rrdr_convert_before_after_to_absolute(
}
static RRDR *rrd2rrdr_fixedstep(
- RRDSET *st
+ ONEWAYALLOC *owa
+ , RRDSET *st
, long points_requested
, long long after_requested
, long long before_requested
@@ -855,7 +856,7 @@ static RRDR *rrd2rrdr_fixedstep(
RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL;
if(duration <= 0 || available_points <= 0)
- return rrdr_create(st, 1, context_param_list);
+ return rrdr_create(owa, st, 1, context_param_list);
// check the number of wanted points in the result
if(unlikely(points_requested < 0)) points_requested = -points_requested;
@@ -1013,7 +1014,7 @@ static RRDR *rrd2rrdr_fixedstep(
// initialize our result set
// this also locks the chart for us
- RRDR *r = rrdr_create(st, points_wanted, context_param_list);
+ RRDR *r = rrdr_create(owa, st, points_wanted, context_param_list);
if(unlikely(!r)) {
#ifdef NETDATA_INTERNAL_CHECKS
error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (uint32_t)duration, points_wanted);
@@ -1216,7 +1217,8 @@ static RRDR *rrd2rrdr_fixedstep(
#ifdef ENABLE_DBENGINE
static RRDR *rrd2rrdr_variablestep(
- RRDSET *st
+ ONEWAYALLOC *owa
+ , RRDSET *st
, long points_requested
, long long after_requested
, long long before_requested
@@ -1242,7 +1244,7 @@ static RRDR *rrd2rrdr_variablestep(
if(duration <= 0 || available_points <= 0) {
freez(region_info_array);
- return rrdr_create(st, 1, context_param_list);
+ return rrdr_create(owa, st, 1, context_param_list);
}
// check the number of wanted points in the result
@@ -1401,7 +1403,7 @@ static RRDR *rrd2rrdr_variablestep(
// initialize our result set
// this also locks the chart for us
- RRDR *r = rrdr_create(st, points_wanted, context_param_list);
+ RRDR *r = rrdr_create(owa, st, points_wanted, context_param_list);
if(unlikely(!r)) {
#ifdef NETDATA_INTERNAL_CHECKS
error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (uint32_t)duration, points_wanted);
@@ -1608,7 +1610,8 @@ static RRDR *rrd2rrdr_variablestep(
#endif //#ifdef ENABLE_DBENGINE
RRDR *rrd2rrdr(
- RRDSET *st
+ ONEWAYALLOC *owa
+ , RRDSET *st
, long points_requested
, long long after_requested
, long long before_requested
@@ -1644,7 +1647,7 @@ RRDR *rrd2rrdr(
first_entry_t = after_requested;
if (context_param_list && !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE)) {
- rebuild_context_param_list(context_param_list, after_requested);
+ rebuild_context_param_list(owa, context_param_list, after_requested);
st = context_param_list->rd ? context_param_list->rd->rrdset : NULL;
if (unlikely(!st))
return NULL;
@@ -1669,7 +1672,7 @@ RRDR *rrd2rrdr(
}
freez(region_info_array);
}
- return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method,
+ return rrd2rrdr_fixedstep(owa, st, points_requested, after_requested, before_requested, group_method,
resampling_time_requested, options, dimensions, rrd_update_every,
first_entry_t, last_entry_t, absolute_period_requested, context_param_list, timeout);
} else {
@@ -1680,13 +1683,13 @@ RRDR *rrd2rrdr(
rrd_update_every, first_entry_t,
last_entry_t, options);
}
- return rrd2rrdr_variablestep(st, points_requested, after_requested, before_requested, group_method,
+ return rrd2rrdr_variablestep(owa, st, points_requested, after_requested, before_requested, group_method,
resampling_time_requested, options, dimensions, rrd_update_every,
first_entry_t, last_entry_t, absolute_period_requested, region_info_array, context_param_list, timeout);
}
}
#endif
- return rrd2rrdr_fixedstep(st, points_requested, after_requested, before_requested, group_method,
+ return rrd2rrdr_fixedstep(owa, st, points_requested, after_requested, before_requested, group_method,
resampling_time_requested, options, dimensions,
rrd_update_every, first_entry_t, last_entry_t, absolute_period_requested, context_param_list, timeout);
}
diff --git a/web/api/queries/rrdr.c b/web/api/queries/rrdr.c
index b64868222d..03b71db558 100644
--- a/web/api/queries/rrdr.c
+++ b/web/api/queries/rrdr.c
@@ -83,7 +83,7 @@ inline static void rrdr_unlock_rrdset(RRDR *r) {
}
}
-inline void rrdr_free(RRDR *r)
+inline void rrdr_free(ONEWAYALLOC *owa, RRDR *r)
{
if(unlikely(!r)) {
error("NULL value given!");
@@ -91,21 +91,21 @@ inline void rrdr_free(RRDR *r)
}
rrdr_unlock_rrdset(r);
- freez(r->t);
- freez(r->v);
- freez(r->o);
- freez(r->od);
- freez(r);
+ onewayalloc_freez(owa, r->t);
+ onewayalloc_freez(owa, r->v);
+ onewayalloc_freez(owa, r->o);
+ onewayalloc_freez(owa, r->od);
+ onewayalloc_freez(owa, r);
}
-RRDR *rrdr_create(struct rrdset *st, long n, struct context_param *context_param_list)
+RRDR *rrdr_create(ONEWAYALLOC *owa, struct rrdset *st, long n, struct context_param *context_param_list)
{
if (unlikely(!st)) {
error("NULL value given!");
return NULL;
}
- RRDR *r = callocz(1, sizeof(RRDR));
+ RRDR *r = onewayalloc_callocz(owa, 1, sizeof(RRDR));
r->st = st;
if (!context_param_list || !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE)) {
@@ -126,10 +126,10 @@ RRDR *rrdr_create(struct rrdset *st, long n, struct context_param *context_param
r->n = n;
- r->t = callocz((size_t)n, sizeof(time_t));
- r->v = mallocz(n * r->d * sizeof(calculated_number));
- r->o = mallocz(n * r->d * sizeof(RRDR_VALUE_FLAGS));
- r->od = mallocz(r->d * sizeof(RRDR_DIMENSION_FLAGS));
+ r->t = onewayalloc_callocz(owa, (size_t)n, sizeof(time_t));
+ r->v = onewayalloc_mallocz(owa, n * r->d * sizeof(calculated_number));
+ r->o = onewayalloc_mallocz(owa, n * r->d * sizeof(RRDR_VALUE_FLAGS));
+ r->od = onewayalloc_mallocz(owa, r->d * sizeof(RRDR_DIMENSION_FLAGS));
// set the hidden flag on hidden dimensions
int c;
diff --git a/web/api/queries/rrdr.h b/web/api/queries/rrdr.h
index bd94e56e2b..00125ddf57 100644
--- a/web/api/queries/rrdr.h
+++ b/web/api/queries/rrdr.h
@@ -102,13 +102,14 @@ typedef struct rrdresult {
#define rrdr_rows(r) ((r)->rows)
#include "database/rrd.h"
-extern void rrdr_free(RRDR *r);
-extern RRDR *rrdr_create(struct rrdset *st, long n, struct context_param *context_param_list);
+extern void rrdr_free(ONEWAYALLOC *owa, RRDR *r);
+extern RRDR *rrdr_create(ONEWAYALLOC *owa, struct rrdset *st, long n, struct context_param *context_param_list);
#include "../web_api_v1.h"
#include "web/api/queries/query.h"
extern RRDR *rrd2rrdr(
+ ONEWAYALLOC *owa,
RRDSET *st, long points_requested, long long after_requested, long long before_requested,
RRDR_GROUPING group_method, long resampling_time_requested, RRDR_OPTIONS options, const char *dimensions,
struct context_param *context_param_list, int timeout);
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 8cf89d38d5..54c5e52808 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -512,6 +512,7 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
fix_google_param(outFileName);
RRDSET *st = NULL;
+ ONEWAYALLOC *owa = onewayalloc_create(0);
if((!chart || !*chart) && (!context)) {
buffer_sprintf(w->response.data, "No chart id is given at the request.");
@@ -519,8 +520,10 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
}
struct context_param *context_param_list = NULL;
+
if (context && !chart) {
RRDSET *st1;
+
uint32_t context_hash = simple_hash(context);
rrdhost_rdlock(host);
@@ -532,14 +535,14 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
(!chart_label_key || rrdset_contains_label_keylist(st1, chart_label_key)) &&
(!chart_labels_filter ||
rrdset_matches_label_keys(st1, chart_labels_filter, words, hash_key_list, &word_count, MAX_CHART_LABELS_FILTER)))
- build_context_param_list(&context_param_list, st1);
+ build_context_param_list(owa, &context_param_list, st1);
}
rrdhost_unlock(host);
if (likely(context_param_list && context_param_list->rd)) // Just set the first one
st = context_param_list->rd->rrdset;
else {
if (!chart_label_key && !chart_labels_filter)
- sql_build_context_param_list(&context_param_list, host, context, NULL);
+ sql_build_context_param_list(owa, &context_param_list, host, context, NULL);
}
}
else {
@@ -549,14 +552,14 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
if (likely(st))
st->last_accessed_time = now_realtime_sec();
else
- sql_build_context_param_list(&context_param_list, host, NULL, chart);
+ sql_build_context_param_list(owa, &context_param_list, host, NULL, chart);
}
if (!st) {
if (likely(context_param_list && context_param_list->rd && context_param_list->rd->rrdset))
st = context_param_list->rd->rrdset;
else {
- free_context_param_list(&context_param_list);
+ free_context_param_list(owa, &context_param_list);
context_param_list = NULL;
}
}
@@ -630,12 +633,12 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
buffer_strcat(w->response.data, "(");
}
- ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format,
+ ret = rrdset2anything_api_v1(owa, st, w->response.data, dimensions, format,
points, after, before, group, group_time,
options, &last_timestamp_in_data, context_param_list,
chart_label_key, max_anomaly_rates, timeout);
- free_context_param_list(&context_param_list);
+ free_context_param_list(owa, &context_param_list);
if(format == DATASOURCE_DATATABLE_JSONP) {
if(google_timestamp < last_timestamp_in_data)
@@ -652,7 +655,8 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
else if(format == DATASOURCE_JSONP)
buffer_strcat(w->response.data, ");");
- cleanup:
+cleanup:
+ onewayalloc_destroy(owa);
buffer_free(dimensions);
return ret;
}