Improve context load (#16659)
* Improve single thread load. Handle thread creation failure as well Remove RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS Improve chart label cleanup * Init thread index
Stelios Fragkakis committed
Jan 15, 2024 at 18:25 UTC
10721be4ec3feaf72ff45856a7c447fe95a4b435
3 files changed
+102
-71
database/rrd.h
+5
-6
@@ -975,19 +975,18 @@ typedef enum __attribute__ ((__packed__)) rrdhost_flags {
975
976
// ACLK
977
RRDHOST_FLAG_ACLK_STREAM_CONTEXTS = (1 << 21), // when set, we should send ACLK stream context updates
978
- RRDHOST_FLAG_ACLK_STREAM_ALERTS = (1 << 22), // set when the receiver part is disconnected
978
+ RRDHOST_FLAG_ACLK_STREAM_ALERTS = (1 << 22), // Host should stream alerts
979
980
// Metadata
981
RRDHOST_FLAG_METADATA_UPDATE = (1 << 23), // metadata needs to be stored in the database
982
RRDHOST_FLAG_METADATA_LABELS = (1 << 24), // metadata needs to be stored in the database
983
RRDHOST_FLAG_METADATA_INFO = (1 << 25), // metadata needs to be stored in the database
984
- RRDHOST_FLAG_PENDING_CONTEXT_LOAD = (1 << 26), // metadata needs to be stored in the database
985
- RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS = (1 << 27), // metadata needs to be stored in the database
984
+ RRDHOST_FLAG_PENDING_CONTEXT_LOAD = (1 << 26), // Context needs to be loaded
985
987
- RRDHOST_FLAG_METADATA_CLAIMID = (1 << 28), // metadata needs to be stored in the database
988
- RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED = (1 << 29), // set when the receiver part is disconnected
986
+ RRDHOST_FLAG_METADATA_CLAIMID = (1 << 27), // metadata needs to be stored in the database
987
+ RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED = (1 << 28), // set when the receiver part is disconnected
988
990
- RRDHOST_FLAG_GLOBAL_FUNCTIONS_UPDATED = (1 << 30), // set when the host has updated global functions
989
+ RRDHOST_FLAG_GLOBAL_FUNCTIONS_UPDATED = (1 << 29), // set when the host has updated global functions
990
} RRDHOST_FLAGS;
991
992
#define rrdhost_flag_check(host, flag) (__atomic_load_n(&((host)->flags), __ATOMIC_SEQ_CST) & (flag))
database/rrdhost.c
+1
-1
@@ -1739,7 +1739,7 @@ void rrdhost_status(RRDHOST *host, time_t now, RRDHOST_STATUS *s) {
1739
s->db.instances = host->rrdctx.instances;
1740
s->db.contexts = dictionary_entries(host->rrdctx.contexts);
1741
if(!s->db.first_time_s || !s->db.last_time_s || !s->db.metrics || !s->db.instances || !s->db.contexts ||
1742
- (flags & (RRDHOST_FLAG_PENDING_CONTEXT_LOAD|RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS)))
1742
+ (flags & (RRDHOST_FLAG_PENDING_CONTEXT_LOAD)))
1743
s->db.status = RRDHOST_DB_STATUS_INITIALIZING;
1744
else
1745
s->db.status = RRDHOST_DB_STATUS_QUERYABLE;
database/sqlite/sqlite_metadata.c
+96
-64
@@ -873,7 +873,7 @@ static void check_dimension_metadata(struct metadata_wc *wc)
873
uint32_t total_checked = 0;
874
uint32_t total_deleted = 0;
875
876
- internal_error(true, "METADATA: Checking dimensions starting after row %"PRIu64, last_row_id);
876
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Checking dimensions starting after row %" PRIu64, last_row_id);
877
878
bool more_to_do = run_cleanup_loop(
879
res,
@@ -896,8 +896,10 @@ static void check_dimension_metadata(struct metadata_wc *wc)
896
next_execution_t = now + METADATA_DIM_CHECK_INTERVAL;
897
}
898
899
- internal_error(true,
900
- "METADATA: Dimensions checked %u, deleted %u. Checks will %s in %lld seconds",
899
+ nd_log(
900
+ NDLS_DAEMON,
901
+ NDLP_DEBUG,
902
+ "Dimensions checked %u, deleted %u. Checks will %s in %lld seconds",
903
total_checked,
904
total_deleted,
905
last_row_id ? "resume" : "restart",
@@ -932,7 +934,7 @@ static void check_chart_metadata(struct metadata_wc *wc)
934
uint32_t total_checked = 0;
935
uint32_t total_deleted = 0;
936
935
- internal_error(true, "METADATA: Checking charts starting after row %"PRIu64, last_row_id);
937
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Checking charts starting after row %" PRIu64, last_row_id);
938
939
sqlite3_stmt *check_res = NULL;
940
sqlite3_stmt *action_res = NULL;
@@ -963,8 +965,10 @@ static void check_chart_metadata(struct metadata_wc *wc)
965
next_execution_t = now + METADATA_CHART_CHECK_INTERVAL;
966
}
967
966
- internal_error(true,
967
- "METADATA: Charts checked %u, deleted %u. Checks will %s in %lld seconds",
968
+ nd_log(
969
+ NDLS_DAEMON,
970
+ NDLP_DEBUG,
971
+ "Charts checked %u, deleted %u. Checks will %s in %lld seconds",
972
total_checked,
973
total_deleted,
974
last_row_id ? "resume" : "restart",
@@ -1000,7 +1004,7 @@ static void check_label_metadata(struct metadata_wc *wc)
1004
uint32_t total_checked = 0;
1005
uint32_t total_deleted = 0;
1006
1003
- internal_error(true,"METADATA: Checking charts labels starting after row %"PRIu64, last_row_id);
1007
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Checking charts labels starting after row %" PRIu64, last_row_id);
1008
1009
sqlite3_stmt *check_res = NULL;
1010
sqlite3_stmt *action_res = NULL;
@@ -1032,8 +1036,10 @@ static void check_label_metadata(struct metadata_wc *wc)
1036
next_execution_t = now + METADATA_LABEL_CHECK_INTERVAL;
1037
}
1038
1035
- internal_error(true,
1036
- "METADATA: Chart labels checked %u, deleted %u. Checks will %s in %lld seconds",
1039
+ nd_log(
1040
+ NDLS_DAEMON,
1041
+ NDLP_DEBUG,
1042
+ "Chart labels checked %u, deleted %u. Checks will %s in %lld seconds",
1043
total_checked,
1044
total_deleted,
1045
last_row_id ? "resume" : "restart",
@@ -1223,13 +1229,17 @@ static void restore_host_context(void *arg)
1229
rrdhost_load_rrdcontext_data(host);
1230
usec_t ended_ut = now_monotonic_usec(); (void)ended_ut;
1231
1226
- rrdhost_flag_clear(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD | RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS);
1232
+ rrdhost_flag_clear(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD);
1233
1234
#ifdef ENABLE_ACLK
1235
aclk_queue_node_info(host, false);
1236
#endif
1237
1232
- internal_error(true, "METADATA: 'host:%s' context load in %0.2f ms", rrdhost_hostname(host),
1238
+ nd_log(
1239
+ NDLS_DAEMON,
1240
+ NDLP_DEBUG,
1241
+ "Contexts for host %s loaded in %0.2f ms",
1242
+ rrdhost_hostname(host),
1243
(double)(ended_ut - started_ut) / USEC_PER_MS);
1244
1245
__atomic_store_n(&hclt->finished, true, __ATOMIC_RELEASE);
@@ -1246,12 +1256,15 @@ static void after_start_host_load_context(uv_work_t *req, int status __maybe_unu
1256
1257
static void cleanup_finished_threads(struct host_context_load_thread *hclt, size_t max_thread_slots, bool wait)
1258
{
1259
+ if (!hclt)
1260
+ return;
1261
+
1262
for (size_t index = 0; index < max_thread_slots; index++) {
1263
if (__atomic_load_n(&(hclt[index].finished), __ATOMIC_RELAXED)
1264
|| (wait && __atomic_load_n(&(hclt[index].busy), __ATOMIC_ACQUIRE))) {
1265
int rc = uv_thread_join(&(hclt[index].thread));
1266
if (rc)
1254
- netdata_log_error("Failed to join thread, rc = %d",rc);
1267
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "Failed to join thread, rc = %d", rc);
1268
__atomic_store_n(&(hclt[index].busy), false, __ATOMIC_RELEASE);
1269
__atomic_store_n(&(hclt[index].finished), false, __ATOMIC_RELEASE);
1270
}
@@ -1290,40 +1303,50 @@ static void start_all_host_load_context(uv_work_t *req __maybe_unused)
1303
size_t max_threads = MIN(get_netdata_cpus() / 2, 6);
1304
if (max_threads < 1)
1305
max_threads = 1;
1293
- nd_log(NDLS_DAEMON, NDLP_DEBUG, "METADATA: Using %zu threads for context loading", max_threads);
1294
- struct host_context_load_thread *hclt = callocz(max_threads, sizeof(*hclt));
1306
1296
- size_t thread_index;
1307
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Using %zu threads for context loading", max_threads);
1308
+ struct host_context_load_thread *hclt = max_threads > 1 ? callocz(max_threads, sizeof(*hclt)) : NULL;
1309
+
1310
+ size_t thread_index = 0;
1311
dfe_start_reentrant(rrdhost_root_index, host) {
1298
- if (rrdhost_flag_check(host, RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS) ||
1299
- !rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD))
1312
+ if (!rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD))
1313
continue;
1314
1302
- rrdhost_flag_set(host, RRDHOST_FLAG_CONTEXT_LOAD_IN_PROGRESS);
1303
- internal_error(true, "METADATA: 'host:%s' loading context", rrdhost_hostname(host));
1315
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Loading context for host %s", rrdhost_hostname(host));
1316
1305
- bool found_slot = false;
1306
- do {
1307
- if (metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN))
1308
- break;
1317
+ int rc = 0;
1318
+ if (hclt) {
1319
+ bool found_slot = false;
1320
+ do {
1321
+ if (metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN))
1322
+ break;
1323
+
1324
+ cleanup_finished_threads(hclt, max_threads, false);
1325
+ found_slot = find_available_thread_slot(hclt, max_threads, &thread_index);
1326
+ } while (!found_slot);
1327
1310
- cleanup_finished_threads(hclt, max_threads, false);
1311
- found_slot = find_available_thread_slot(hclt, max_threads, &thread_index);
1312
- } while (!found_slot);
1328
+ if (metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN))
1329
+ break;
1330
1314
- if (metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN))
1315
- break;
1331
+ __atomic_store_n(&hclt[thread_index].busy, true, __ATOMIC_RELAXED);
1332
+ hclt[thread_index].host = host;
1333
+ rc = uv_thread_create(&hclt[thread_index].thread, restore_host_context, &hclt[thread_index]);
1334
+ }
1335
+ // if single thread or thread creation failed
1336
+ if (rc || !hclt) {
1337
+ struct host_context_load_thread hclt_sync = {.host = host};
1338
+ restore_host_context(&hclt_sync);
1339
1317
- __atomic_store_n(&hclt[thread_index].busy, true, __ATOMIC_RELAXED);
1318
- hclt[thread_index].host = host;
1319
- fatal_assert(0 == uv_thread_create(&hclt[thread_index].thread, restore_host_context, &hclt[thread_index]));
1340
+ if (metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN))
1341
+ break;
1342
+ }
1343
}
1344
dfe_done(host);
1345
1346
cleanup_finished_threads(hclt, max_threads, true);
1347
freez(hclt);
1348
usec_t ended_ut = now_monotonic_usec(); (void)ended_ut;
1326
- nd_log(NDLS_DAEMON, NDLP_DEBUG, "METADATA: host contexts loaded in %0.2f ms", (double)(ended_ut - started_ut) / USEC_PER_MS);
1349
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Host contexts loaded in %0.2f ms", (double)(ended_ut - started_ut) / USEC_PER_MS);
1350
1351
worker_is_idle();
1352
}
@@ -1335,11 +1358,10 @@ static void after_metadata_hosts(uv_work_t *req, int status __maybe_unused)
1358
struct metadata_wc *wc = data->wc;
1359
1360
metadata_flag_clear(wc, METADATA_FLAG_PROCESSING);
1338
- internal_error(true, "METADATA: scanning hosts complete");
1339
- if (unlikely(wc->scan_complete)) {
1361
+
1362
+ if (unlikely(wc->scan_complete))
1363
completion_mark_complete(wc->scan_complete);
1341
- internal_error(true, "METADATA: Sending completion done");
1342
- }
1364
+
1365
freez(data);
1366
}
1367
@@ -1448,6 +1470,30 @@ struct host_chart_label_cleanup {
1470
Word_t count;
1471
};
1472
1473
+static void do_chart_label_cleanup(struct host_chart_label_cleanup *cl_cleanup_data)
1474
+{
1475
+ if (!cl_cleanup_data)
1476
+ return;
1477
+
1478
+ Word_t Index = 0;
1479
+ bool first = true;
1480
+ Pvoid_t *PValue;
1481
+ while ((PValue = JudyLFirstThenNext(cl_cleanup_data->JudyL, &Index, &first))) {
1482
+ char *machine_guid = *PValue;
1483
+
1484
+ RRDHOST *host = rrdhost_find_by_guid(machine_guid);
1485
+ if (likely(!host)) {
1486
+ uuid_t host_uuid;
1487
+ if (!uuid_parse(machine_guid, host_uuid))
1488
+ delete_host_chart_labels(&host_uuid);
1489
+ }
1490
+
1491
+ freez(machine_guid);
1492
+ }
1493
+ JudyLFreeArray(&cl_cleanup_data->JudyL, PJE0);
1494
+ freez(cl_cleanup_data);
1495
+}
1496
+
1497
// Worker thread to scan hosts for pending metadata to store
1498
static void start_metadata_hosts(uv_work_t *req __maybe_unused)
1499
{
@@ -1461,30 +1507,10 @@ static void start_metadata_hosts(uv_work_t *req __maybe_unused)
1507
1508
BUFFER *work_buffer = data->work_buffer;
1509
usec_t all_started_ut = now_monotonic_usec(); (void)all_started_ut;
1464
- internal_error(true, "METADATA: checking all hosts...");
1510
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Checking all hosts started");
1511
usec_t started_ut = now_monotonic_usec(); (void)started_ut;
1512
1467
- struct host_chart_label_cleanup *cl_cleanup_data = data->data;
1468
-
1469
- if (cl_cleanup_data) {
1470
- Word_t Index = 0;
1471
- bool first = true;
1472
- Pvoid_t *PValue;
1473
- while ((PValue = JudyLFirstThenNext(cl_cleanup_data->JudyL, &Index, &first))) {
1474
- char *machine_guid = *PValue;
1475
-
1476
- host = rrdhost_find_by_guid(machine_guid);
1477
- if (likely(!host)) {
1478
- uuid_t host_uuid;
1479
- if (!uuid_parse(machine_guid, host_uuid))
1480
- delete_host_chart_labels(&host_uuid);
1481
- }
1482
-
1483
- freez(machine_guid);
1484
- }
1485
- JudyLFreeArray(&cl_cleanup_data->JudyL, PJE0);
1486
- freez(cl_cleanup_data);
1487
- }
1513
+ do_chart_label_cleanup((struct host_chart_label_cleanup *) data->data);
1514
1515
bool run_again = false;
1516
worker_is_busy(UV_EVENT_METADATA_STORE);
@@ -1550,12 +1576,15 @@ static void start_metadata_hosts(uv_work_t *req __maybe_unused)
1576
if (unlikely(metadata_scan_host(host, data->max_count, use_transaction, work_buffer, &query_counter))) {
1577
run_again = true;
1578
rrdhost_flag_set(host,RRDHOST_FLAG_METADATA_UPDATE);
1553
- internal_error(true,"METADATA: 'host:%s': scheduling another run, more charts to store", rrdhost_hostname(host));
1579
}
1580
usec_t ended_ut = now_monotonic_usec(); (void)ended_ut;
1556
- internal_error(true, "METADATA: 'host:%s': saved metadata with %zu SQL statements, in %0.2f ms",
1557
- rrdhost_hostname(host), query_counter,
1558
- (double)(ended_ut - started_ut) / USEC_PER_MS);
1581
+ nd_log(
1582
+ NDLS_DAEMON,
1583
+ NDLP_DEBUG,
1584
+ "Host %s saved metadata with %zu SQL statements, in %0.2f ms",
1585
+ rrdhost_hostname(host),
1586
+ query_counter,
1587
+ (double)(ended_ut - started_ut) / USEC_PER_MS);
1588
}
1589
dfe_done(host);
1590
@@ -1563,8 +1592,11 @@ static void start_metadata_hosts(uv_work_t *req __maybe_unused)
1592
transaction_started = db_execute(db_meta, "COMMIT TRANSACTION");
1593
1594
usec_t all_ended_ut = now_monotonic_usec(); (void)all_ended_ut;
1566
- internal_error(true, "METADATA: checking all hosts completed in %0.2f ms",
1567
- (double)(all_ended_ut - all_started_ut) / USEC_PER_MS);
1595
+ nd_log(
1596
+ NDLS_DAEMON,
1597
+ NDLP_DEBUG,
1598
+ "Checking all hosts completed in %0.2f ms",
1599
+ (double)(all_ended_ut - all_started_ut) / USEC_PER_MS);
1600
1601
if (unlikely(run_again))
1602
wc->metadata_check_after = now_realtime_sec() + METADATA_HOST_CHECK_IMMEDIATE;