@cryptotaxi247 / netdata-1 / commits / 3f7877783

avoid memory allocations for alert transitions facets processing (#15318)

Costa Tsaousis committed Jul 6, 2023 at 17:19 UTC 3f787778390f11a9f6fb3ae9e7e2aeb36b1b7e53
2 files changed +103 -64
database/contexts/api_v2.c
+103 -60
@@ -72,8 +72,8 @@ struct alert_transitions_callback_data {
72 uint32_t limit;
73 uint32_t items;
74
75 - struct sql_alert_transition_data *base; // double linked list - last item is base->prev
76 - struct sql_alert_transition_data *last_added; // the last item added, not the last of the list
75 + struct sql_alert_transition_fixed_size *base; // double linked list - last item is base->prev
76 + struct sql_alert_transition_fixed_size *last_added; // the last item added, not the last of the list
77
78 struct {
79 size_t items;
@@ -1368,50 +1368,86 @@ static void contexts_v2_alerts_to_json(BUFFER *wb, struct rrdcontext_to_json_v2_
1368 }
1369 }
1370
1371 -static struct sql_alert_transition_data *contexts_v2_alert_transition_dup(struct sql_alert_transition_data *t, const char *machine_guid) {
1372 - struct sql_alert_transition_data *n = mallocz(sizeof(*t));
1373 - memcpy(n, t, sizeof(*t));
1374 -
1375 - n->transition_id = mallocz(sizeof(*t->transition_id));
1376 - memcpy(n->transition_id, t->transition_id, sizeof(*t->transition_id));
1377 -
1378 - n->host_id = NULL;
1379 -
1380 - n->config_hash_id = mallocz(sizeof(*t->config_hash_id));
1381 - memcpy(n->config_hash_id, t->config_hash_id, sizeof(*t->config_hash_id));
1371 +#define SQL_TRANSITION_DATA_SMALL_STRING (6 * 8)
1372 +#define SQL_TRANSITION_DATA_MEDIUM_STRING (12 * 8)
1373 +#define SQL_TRANSITION_DATA_BIG_STRING 512
1374 +
1375 +struct sql_alert_transition_fixed_size {
1376 + usec_t global_id;
1377 + uuid_t transition_id;
1378 + uuid_t host_id;
1379 + uuid_t config_hash_id;
1380 + uint32_t alarm_id;
1381 + char alert_name[SQL_TRANSITION_DATA_SMALL_STRING];
1382 + char chart[RRD_ID_LENGTH_MAX];
1383 + char chart_context[SQL_TRANSITION_DATA_MEDIUM_STRING];
1384 + char family[SQL_TRANSITION_DATA_SMALL_STRING];
1385 + char recipient[SQL_TRANSITION_DATA_MEDIUM_STRING];
1386 + char units[SQL_TRANSITION_DATA_SMALL_STRING];
1387 + char exec[SQL_TRANSITION_DATA_BIG_STRING];
1388 + char info[SQL_TRANSITION_DATA_BIG_STRING];
1389 + char classification[SQL_TRANSITION_DATA_SMALL_STRING];
1390 + char type[SQL_TRANSITION_DATA_SMALL_STRING];
1391 + char component[SQL_TRANSITION_DATA_SMALL_STRING];
1392 + time_t when_key;
1393 + time_t duration;
1394 + time_t non_clear_duration;
1395 + uint64_t flags;
1396 + time_t delay_up_to_timestamp;
1397 + time_t exec_run_timestamp;
1398 + int exec_code;
1399 + int new_status;
1400 + int old_status;
1401 + int delay;
1402 + time_t last_repeat;
1403 + NETDATA_DOUBLE new_value;
1404 + NETDATA_DOUBLE old_value;
1405 +
1406 + char machine_guid[UUID_STR_LEN];
1407 + struct sql_alert_transition_fixed_size *next;
1408 + struct sql_alert_transition_fixed_size *prev;
1409 +};
1410
1383 - n->alert_name = t->alert_name && *t->alert_name ? strdupz(t->alert_name) : NULL;
1384 - n->chart = t->chart && *t->chart ? strdupz(t->chart) : NULL;
1385 - n->chart_context = t->chart_context && *t->chart_context ? strdupz(t->chart_context) : NULL;
1386 - n->family = NULL;
1387 - n->recipient = t->recipient && *t->recipient ? strdupz(t->recipient) : NULL;
1388 - n->units = t->units && *t->units ? strdupz(t->units) : NULL;
1389 - n->info = t->info && *t->info ? strdupz(t->info) : NULL;
1390 - n->classification = t->classification && *t->classification ? strdupz(t->classification) : NULL;
1391 - n->type = t->type && *t->type ? strdupz(t->type) : NULL;
1392 - n->component = t->component && *t->component ? strdupz(t->component) : NULL;
1393 - n->exec = (t->exec && *t->exec) ? strdupz(t->exec) : NULL;
1411 +static struct sql_alert_transition_fixed_size *contexts_v2_alert_transition_dup(struct sql_alert_transition_data *t, const char *machine_guid, struct sql_alert_transition_fixed_size *dst) {
1412 + struct sql_alert_transition_fixed_size *n = dst ? dst : mallocz(sizeof(*n));
1413 +
1414 + n->global_id = t->global_id;
1415 + uuid_copy(n->transition_id, *t->transition_id);
1416 + uuid_copy(n->host_id, *t->host_id);
1417 + uuid_copy(n->config_hash_id, *t->config_hash_id);
1418 + n->alarm_id = t->alarm_id;
1419 + strncpyz(n->alert_name, t->alert_name ? t->alert_name : "", sizeof(n->alert_name) - 1);
1420 + strncpyz(n->chart, t->chart ? t->chart : "", sizeof(n->chart) - 1);
1421 + strncpyz(n->chart_context, t->chart_context ? t->chart_context : "", sizeof(n->chart_context) - 1);
1422 + strncpyz(n->family, t->family ? t->family : "", sizeof(n->family) - 1);
1423 + strncpyz(n->recipient, t->recipient ? t->recipient : "", sizeof(n->recipient) - 1);
1424 + strncpyz(n->units, t->units ? t->units : "", sizeof(n->units) - 1);
1425 + strncpyz(n->exec, t->exec ? t->exec : "", sizeof(n->exec) - 1);
1426 + strncpyz(n->info, t->info ? t->info : "", sizeof(n->info) - 1);
1427 + strncpyz(n->classification, t->classification ? t->classification : "", sizeof(n->classification) - 1);
1428 + strncpyz(n->type, t->type ? t->type : "", sizeof(n->type) - 1);
1429 + strncpyz(n->component, t->component ? t->component : "", sizeof(n->component) - 1);
1430 + n->when_key = t->when_key;
1431 + n->duration = t->duration;
1432 + n->non_clear_duration = t->non_clear_duration;
1433 + n->flags = t->flags;
1434 + n->delay_up_to_timestamp = t->delay_up_to_timestamp;
1435 + n->exec_run_timestamp = t->exec_run_timestamp;
1436 + n->exec_code = t->exec_code;
1437 + n->new_status = t->new_status;
1438 + n->old_status = t->old_status;
1439 + n->delay = t->delay;
1440 + n->last_repeat = t->last_repeat;
1441 + n->new_value = t->new_value;
1442 + n->old_value = t->old_value;
1443
1444 memcpy(n->machine_guid, machine_guid, sizeof(n->machine_guid));
1445 + n->next = n->prev = NULL;
1446
1447 return n;
1448 }
1449
1400 -static void contexts_v2_alert_transition_free(struct sql_alert_transition_data *t) {
1401 - freez(t->transition_id);
1402 - freez(t->host_id);
1403 - freez(t->config_hash_id);
1404 - freez((void *)t->alert_name);
1405 - freez((void *)t->chart);
1406 - freez((void *)t->chart_context);
1407 - freez((void *)t->family);
1408 - freez((void *)t->recipient);
1409 - freez((void *)t->units);
1410 - freez((void *)t->info);
1411 - freez((void *)t->classification);
1412 - freez((void *)t->type);
1413 - freez((void *)t->component);
1414 - freez((void *)t->exec);
1450 +static void contexts_v2_alert_transition_free(struct sql_alert_transition_fixed_size *t) {
1451 freez(t);
1452 }
1453
@@ -1423,14 +1459,14 @@ static inline void contexts_v2_alert_transition_keep(struct alert_transitions_ca
1459 }
1460
1461 if(unlikely(!d->base)) {
1426 - d->last_added = contexts_v2_alert_transition_dup(t, machine_guid);
1462 + d->last_added = contexts_v2_alert_transition_dup(t, machine_guid, NULL);
1463 DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(d->base, d->last_added, prev, next);
1464 d->items++;
1465 d->stats.first++;
1466 return;
1467 }
1468
1433 - struct sql_alert_transition_data *last = d->last_added;
1469 + struct sql_alert_transition_fixed_size *last = d->last_added;
1470 while(last->prev != d->base->prev && t->global_id > last->prev->global_id) {
1471 last = last->prev;
1472 d->stats.backwards++;
@@ -1449,13 +1485,20 @@ static inline void contexts_v2_alert_transition_keep(struct alert_transitions_ca
1485 }
1486
1487 d->items++;
1452 - d->last_added = contexts_v2_alert_transition_dup(t, machine_guid);
1488
1489 if(t->global_id > last->global_id) {
1490 + if(d->items > d->limit) {
1491 + d->items--;
1492 + d->stats.shifts++;
1493 + d->last_added = d->base->prev;
1494 + DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(d->base, d->last_added, prev, next);
1495 + d->last_added = contexts_v2_alert_transition_dup(t, machine_guid, d->last_added);
1496 + }
1497 DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(d->base, d->last_added, prev, next);
1498 d->stats.prepend++;
1499 }
1500 else {
1501 + d->last_added = contexts_v2_alert_transition_dup(t, machine_guid, NULL);
1502 DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(d->base, d->last_added, prev, next);
1503 d->stats.append++;
1504 }
@@ -1463,7 +1506,7 @@ static inline void contexts_v2_alert_transition_keep(struct alert_transitions_ca
1506 while(d->items > d->limit) {
1507 // we have to remove something
1508
1466 - struct sql_alert_transition_data *tmp = d->base->prev;
1509 + struct sql_alert_transition_fixed_size *tmp = d->base->prev;
1510 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(d->base, tmp, prev, next);
1511 d->items--;
1512
@@ -1605,30 +1648,30 @@ static void contexts_v2_alert_transitions_to_json(BUFFER *wb, struct rrdcontext_
1648 buffer_json_array_close(wb); // facets
1649
1650 buffer_json_member_add_array(wb, "transitions");
1608 - for(struct sql_alert_transition_data *t = data.base; t ; t = t->next) {
1651 + for(struct sql_alert_transition_fixed_size *t = data.base; t ; t = t->next) {
1652 buffer_json_add_array_item_object(wb);
1653 {
1654 RRDHOST *host = rrdhost_find_by_guid(t->machine_guid);
1655
1656 buffer_json_member_add_uint64(wb, "gi", t->global_id);
1614 - buffer_json_member_add_uuid(wb, "transition_id", t->transition_id);
1615 - buffer_json_member_add_uuid(wb, "config_hash_id", t->config_hash_id);
1657 + buffer_json_member_add_uuid(wb, "transition_id", &t->transition_id);
1658 + buffer_json_member_add_uuid(wb, "config_hash_id", &t->config_hash_id);
1659 buffer_json_member_add_string(wb, "machine_guid", t->machine_guid);
1660
1661 if(host && host->node_id)
1662 buffer_json_member_add_uuid(wb, "node_id", host->node_id);
1663
1621 - buffer_json_member_add_string(wb, "alert", t->alert_name);
1622 - buffer_json_member_add_string(wb, "instance", t->chart);
1623 - buffer_json_member_add_string(wb, "context", t->chart_context);
1624 - // buffer_json_member_add_string(wb, "family", t->family);
1625 - buffer_json_member_add_string(wb, "component", t->component);
1626 - buffer_json_member_add_string(wb, "classification", t->classification);
1627 - buffer_json_member_add_string(wb, "type", t->type);
1664 + buffer_json_member_add_string(wb, "alert", *t->alert_name ? t->alert_name : NULL);
1665 + buffer_json_member_add_string(wb, "instance", *t->chart ? t->chart : NULL);
1666 + buffer_json_member_add_string(wb, "context", *t->chart_context ? t->chart_context : NULL);
1667 + // buffer_json_member_add_string(wb, "family", *t->family ? t->family : NULL);
1668 + buffer_json_member_add_string(wb, "component", *t->component ? t->component : NULL);
1669 + buffer_json_member_add_string(wb, "classification", *t->classification ? t->classification : NULL);
1670 + buffer_json_member_add_string(wb, "type", *t->type ? t->type : NULL);
1671
1672 buffer_json_member_add_time_t(wb, "when", t->when_key);
1630 - buffer_json_member_add_string(wb, "info", t->info);
1631 - buffer_json_member_add_string(wb, "units", t->units);
1673 + buffer_json_member_add_string(wb, "info", *t->info ? t->info : "");
1674 + buffer_json_member_add_string(wb, "units", *t->units ? t->units : NULL);
1675 buffer_json_member_add_object(wb, "new");
1676 {
1677 buffer_json_member_add_string(wb, "status", rrdcalc_status2string(t->new_status));
@@ -1650,9 +1693,9 @@ static void contexts_v2_alert_transitions_to_json(BUFFER *wb, struct rrdcontext_
1693 buffer_json_member_add_time_t(wb, "delay", t->delay);
1694 buffer_json_member_add_time_t(wb, "delay_up_to_time", t->delay_up_to_timestamp);
1695 health_entry_flags_to_json_array(wb, "flags", t->flags);
1653 - buffer_json_member_add_string(wb, "exec", (t->exec && *t->exec) ? t->exec : string2str(localhost->health.health_default_exec));
1696 + buffer_json_member_add_string(wb, "exec", *t->exec ? t->exec : string2str(localhost->health.health_default_exec));
1697 buffer_json_member_add_uint64(wb, "exec_code", t->exec_code);
1655 - buffer_json_member_add_string(wb, "to", t->recipient && *t->recipient ? t->recipient : string2str(localhost->health.health_default_recipient));
1698 + buffer_json_member_add_string(wb, "to", *t->recipient ? t->recipient : string2str(localhost->health.health_default_recipient));
1699 }
1700 buffer_json_object_close(wb); // notification
1701 }
@@ -1663,9 +1706,9 @@ static void contexts_v2_alert_transitions_to_json(BUFFER *wb, struct rrdcontext_
1706 if(ctl->options & CONTEXT_V2_OPTION_ALERTS_WITH_CONFIGURATIONS) {
1707 DICTIONARY *configs = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
1708
1666 - for(struct sql_alert_transition_data *t = data.base; t ; t = t->next) {
1709 + for(struct sql_alert_transition_fixed_size *t = data.base; t ; t = t->next) {
1710 char guid[UUID_STR_LEN];
1668 - uuid_unparse_lower(*t->config_hash_id, guid);
1711 + uuid_unparse_lower(t->config_hash_id, guid);
1712 dictionary_set(configs, guid, NULL, 0);
1713 }
1714
@@ -1677,7 +1720,7 @@ static void contexts_v2_alert_transitions_to_json(BUFFER *wb, struct rrdcontext_
1720 }
1721
1722 while(data.base) {
1680 - struct sql_alert_transition_data *t = data.base;
1723 + struct sql_alert_transition_fixed_size *t = data.base;
1724 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(data.base, t, prev, next);
1725 contexts_v2_alert_transition_free(t);
1726 }
database/contexts/rrdcontext.h
-4
@@ -446,10 +446,6 @@ struct sql_alert_transition_data {
446 time_t last_repeat;
447 NETDATA_DOUBLE new_value;
448 NETDATA_DOUBLE old_value;
449 -
450 - char machine_guid[UUID_STR_LEN];
451 - struct sql_alert_transition_data *next;
452 - struct sql_alert_transition_data *prev;
449 };
450
451 struct sql_alert_config_data {