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 {