@cryptotaxi247 / netdata-1 / commits / 3a77de1f5

profile startup and shutdown timings (#14243)

* profile startup and shutdown timings * waste less time waiting for threads to exit

Costa Tsaousis committed Jan 11, 2023 at 23:11 UTC 3a77de1f54b152e677f9261bfdf38532e0151f72
1 file changed +136 -36
daemon/main.c
+136 -36
@@ -226,7 +226,8 @@ static bool service_wait_exit(SERVICE_TYPE service, usec_t timeout_ut) {
226 // signal them to stop
227 size_t last_running = 0;
228 size_t stale_time_ut = 0;
229 - usec_t sleep_ut = 500 * USEC_PER_MS;
229 + usec_t sleep_ut = 50 * USEC_PER_MS;
230 + size_t log_countdown_ut = sleep_ut;
231 do {
232 if(running != last_running)
233 stale_time_ut = 0;
@@ -257,11 +258,17 @@ static bool service_wait_exit(SERVICE_TYPE service, usec_t timeout_ut) {
258 netdata_spinlock_unlock(&service_globals.lock);
259
260 if(running) {
260 - buffer_flush(service_list);
261 - service_to_buffer(service_list, running_services);
262 - info("SERVICE CONTROL: waiting for the following %zu services [ %s] to exit: %s",
263 - running, buffer_tostring(service_list),
264 - running <= 10 ? buffer_tostring(thread_list) : "");
261 + log_countdown_ut -= (log_countdown_ut >= sleep_ut) ? sleep_ut : log_countdown_ut;
262 + if(log_countdown_ut == 0 || running != last_running) {
263 + log_countdown_ut = 20 * sleep_ut;
264 +
265 + buffer_flush(service_list);
266 + service_to_buffer(service_list, running_services);
267 + info("SERVICE CONTROL: waiting for the following %zu services [ %s] to exit: %s",
268 + running, buffer_tostring(service_list),
269 + running <= 10 ? buffer_tostring(thread_list) : "");
270 + }
271 +
272 sleep_usec(sleep_ut);
273 stale_time_ut += sleep_ut;
274 }
@@ -285,18 +292,39 @@ static bool service_wait_exit(SERVICE_TYPE service, usec_t timeout_ut) {
292 return (running == 0);
293 }
294
295 +#define delta_shutdown_time(msg) \
296 + { \
297 + usec_t now_ut = now_monotonic_usec(); \
298 + if(prev_msg) \
299 + info("NETDATA SHUTDOWN: in %7llu ms, %s%s - next: %s", (now_ut - last_ut) / USEC_PER_MS, (timeout)?"(TIMEOUT) ":"", prev_msg, msg); \
300 + else \
301 + info("NETDATA SHUTDOWN: next: %s", msg); \
302 + last_ut = now_ut; \
303 + prev_msg = msg; \
304 + timeout = false; \
305 + }
306 +
307 void netdata_cleanup_and_exit(int ret) {
308 + usec_t started_ut = now_monotonic_usec();
309 + usec_t last_ut = started_ut;
310 + const char *prev_msg = NULL;
311 + bool timeout = false;
312 +
313 error_log_limit_unlimited();
290 - info("EXIT: netdata prepares to exit with code %d...", ret);
314 + info("NETDATA SHUTDOWN: initializing shutdown with code %d...", ret);
315
316 send_statistics("EXIT", ret?"ERROR":"OK","-");
317
318 + delta_shutdown_time("create shutdown file");
319 +
320 char agent_crash_file[FILENAME_MAX + 1];
321 char agent_incomplete_shutdown_file[FILENAME_MAX + 1];
322 snprintfz(agent_crash_file, FILENAME_MAX, "%s/.agent_crash", netdata_configured_varlib_dir);
323 snprintfz(agent_incomplete_shutdown_file, FILENAME_MAX, "%s/.agent_incomplete_shutdown", netdata_configured_varlib_dir);
324 (void) rename(agent_crash_file, agent_incomplete_shutdown_file);
325
326 + delta_shutdown_time("disable maintenance, new queries, new web requests, new streaming connections and aclk");
327 +
328 service_signal_exit(
329 SERVICE_MAINTENANCE
330 | ABILITY_DATA_QUERIES
@@ -305,7 +333,9 @@ void netdata_cleanup_and_exit(int ret) {
333 | SERVICE_ACLK
334 );
335
308 - service_wait_exit(
336 + delta_shutdown_time("stop replication, exporters, ML training, health and web servers threads");
337 +
338 + timeout = !service_wait_exit(
339 SERVICE_REPLICATION
340 | SERVICE_EXPORTERS
341 | SERVICE_ML_TRAINING
@@ -313,38 +343,51 @@ void netdata_cleanup_and_exit(int ret) {
343 | SERVICE_WEB_SERVER
344 , 3 * USEC_PER_SEC);
345
316 - service_wait_exit(
346 + delta_shutdown_time("stop collectors and streaming threads");
347 +
348 + timeout = !service_wait_exit(
349 SERVICE_COLLECTORS
350 | SERVICE_STREAMING
351 , 3 * USEC_PER_SEC);
352
321 - service_wait_exit(
353 + delta_shutdown_time("stop ML prediction and context threads");
354 +
355 + timeout = !service_wait_exit(
356 SERVICE_ML_PREDICTION
357 | SERVICE_CONTEXT
358 , 3 * USEC_PER_SEC);
359
326 - service_wait_exit(
360 + delta_shutdown_time("stop maintenance thread");
361 +
362 + timeout = !service_wait_exit(
363 SERVICE_MAINTENANCE
364 , 3 * USEC_PER_SEC);
365
330 - info("EXIT: cleaning up the database...");
366 + delta_shutdown_time("clean rrdhost database");
367 +
368 rrdhost_cleanup_all();
369
333 - info("EXIT: metasync shutdown prepare...");
370 + delta_shutdown_time("prepare metasync shutdown");
371 +
372 metadata_sync_shutdown_prepare();
373
374 #ifdef ENABLE_ACLK
375 + delta_shutdown_time("signal aclk sync to stop");
376 aclk_sync_exit_all();
377 #endif
378
340 - service_wait_exit(
379 + delta_shutdown_time("stop aclk threads");
380 +
381 + timeout = !service_wait_exit(
382 SERVICE_ACLK
383 , 3 * USEC_PER_SEC);
384
344 - // stop everything else
345 - service_wait_exit(~0, 10 * USEC_PER_SEC);
385 + delta_shutdown_time("stop all remaining worker threads");
386 +
387 + timeout = !service_wait_exit(~0, 10 * USEC_PER_SEC);
388 +
389 + delta_shutdown_time("cancel main threads");
390
347 - info("EXIT: stopping static threads...");
391 cancel_main_threads();
392
393 if(!ret) {
@@ -352,42 +395,59 @@ void netdata_cleanup_and_exit(int ret) {
395
396 #ifdef ENABLE_DBENGINE
397 if(dbengine_enabled) {
355 - info("EXIT: flushing dbengine...");
398 + delta_shutdown_time("flush dbengine tiers");
399 for (size_t tier = 0; tier < storage_tiers; tier++)
400 rrdeng_prepare_exit(multidb_ctx[tier]);
401 }
402 #endif
403
404 // free the database
362 - info("EXIT: freeing database memory...");
405 + delta_shutdown_time("free rrdhost structures");
406 +
407 rrdhost_free_all();
408
409 + delta_shutdown_time("stop metasync threads");
410 +
411 metadata_sync_shutdown();
412
413 #ifdef ENABLE_DBENGINE
414 if(dbengine_enabled) {
369 - info("EXIT: stopping dbengine...");
415 + delta_shutdown_time("stop dbengine tiers");
416 for (size_t tier = 0; tier < storage_tiers; tier++)
417 rrdeng_exit(multidb_ctx[tier]);
418 }
419 #endif
420 }
421
422 + delta_shutdown_time("close SQL context db");
423 +
424 sql_close_context_database();
425 +
426 + delta_shutdown_time("closed SQL main db");
427 +
428 sql_close_database();
429
430 // unlink the pid
431 if(pidfile[0]) {
381 - info("EXIT: removing netdata PID file '%s'...", pidfile);
432 + delta_shutdown_time("remove pid file");
433 +
434 if(unlink(pidfile) != 0)
435 error("EXIT: cannot unlink pidfile '%s'.", pidfile);
436 }
437
438 #ifdef ENABLE_HTTPS
439 + delta_shutdown_time("free openssl structures");
440 security_clean_openssl();
441 #endif
389 - info("EXIT: all done - netdata is now exiting - bye bye...");
442 +
443 + delta_shutdown_time("remove incomplete shutdown file");
444 +
445 (void) unlink(agent_incomplete_shutdown_file);
446 +
447 + delta_shutdown_time("exit");
448 +
449 + usec_t ended_ut = now_monotonic_usec();
450 + info("NETDATA SHUTDOWN: completed in %llu ms - netdata is now exiting - bye bye...", (ended_ut - started_ut) / USEC_PER_MS);
451 exit(ret);
452 }
453
@@ -1178,11 +1238,28 @@ void post_conf_load(char **user)
1238 appconfig_get(&cloud_config, CONFIG_SECTION_GLOBAL, "cloud base url", DEFAULT_CLOUD_BASE_URL);
1239 }
1240
1241 +#define delta_startup_time(msg) \
1242 + { \
1243 + usec_t now_ut = now_monotonic_usec(); \
1244 + if(prev_msg) \
1245 + info("NETDATA STARTUP: in %7llu ms, %s - next: %s", (now_ut - last_ut) / USEC_PER_MS, prev_msg, msg); \
1246 + else \
1247 + info("NETDATA STARTUP: next: %s", msg); \
1248 + last_ut = now_ut; \
1249 + prev_msg = msg; \
1250 + }
1251 +
1252 int pgc_unittest(void);
1253 int mrg_unittest(void);
1254 int julytest(void);
1255
1256 int main(int argc, char **argv) {
1257 + // initialize the system clocks
1258 + clocks_init();
1259 + usec_t started_ut = now_monotonic_usec();
1260 + usec_t last_ut = started_ut;
1261 + const char *prev_msg = NULL;
1262 +
1263 int i;
1264 int config_loaded = 0;
1265 int dont_fork = 0;
@@ -1629,9 +1706,7 @@ int main(int argc, char **argv) {
1706 }
1707 #endif
1708
1632 -
1633 - if(!config_loaded)
1634 - {
1709 + if(!config_loaded) {
1710 load_netdata_conf(NULL, 0);
1711 post_conf_load(&user);
1712 load_cloud_conf(0);
@@ -1642,7 +1717,6 @@ int main(int argc, char **argv) {
1717 appconfig_set(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", "false");
1718 }
1719
1645 -
1720 // ------------------------------------------------------------------------
1721 // initialize netdata
1722 {
@@ -1662,9 +1736,6 @@ int main(int argc, char **argv) {
1736 #endif
1737 #endif
1738
1665 - // initialize the system clocks
1666 - clocks_init();
1667 -
1739 // set libuv worker threads
1740 libuv_worker_threads = get_system_cpus() * 2;
1741
@@ -1749,6 +1820,7 @@ int main(int argc, char **argv) {
1820 // --------------------------------------------------------------------
1821 // Initialize ML configuration
1822
1823 + delta_startup_time("initialize ML");
1824 ml_init();
1825
1826 // --------------------------------------------------------------------
@@ -1757,18 +1829,18 @@ int main(int argc, char **argv) {
1829 // block signals while initializing threads.
1830 // this causes the threads to block signals.
1831
1832 + delta_startup_time("initialize signals");
1833 signals_block();
1834 + signals_init(); // setup the signals we want to use
1835
1762 - // setup the signals we want to use
1836 + // --------------------------------------------------------------------
1837 + // check which threads are enabled and initialize them
1838
1764 - signals_init();
1839 + delta_startup_time("initialize static threads");
1840
1841 // setup threads configs
1842 default_stacksize = netdata_threads_init();
1843
1769 - // --------------------------------------------------------------------
1770 - // check which threads are enabled and initialize them
1771 -
1844 for (i = 0; static_threads[i].name != NULL ; i++) {
1845 struct netdata_static_thread *st = &static_threads[i];
1846
@@ -1788,14 +1860,17 @@ int main(int argc, char **argv) {
1860 // --------------------------------------------------------------------
1861 // create the listening sockets
1862
1863 + delta_startup_time("initialize web server");
1864 +
1865 web_client_api_v1_init();
1866 web_server_threading_selection();
1867
1868 if(web_server_mode != WEB_SERVER_MODE_NONE)
1869 api_listen_sockets_setup();
1796 -
1870 }
1871
1872 + delta_startup_time("set resource limits");
1873 +
1874 #ifdef NETDATA_INTERNAL_CHECKS
1875 if(debug_flags != 0) {
1876 struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
@@ -1813,18 +1888,27 @@ int main(int argc, char **argv) {
1888 else
1889 info("resources control: allowed file descriptors: soft = %zu, max = %zu", (size_t)rlimit_nofile.rlim_cur, (size_t)rlimit_nofile.rlim_max);
1890
1891 +
1892 + delta_startup_time("become daemon");
1893 +
1894 // fork, switch user, create pid file, set process priority
1895 if(become_daemon(dont_fork, user) == -1)
1896 fatal("Cannot daemonize myself.");
1897
1898 info("netdata started on pid %d.", getpid());
1899
1900 + delta_startup_time("initialize threads after fork");
1901 +
1902 netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize));
1903
1904 // initialize internal registry
1905 + delta_startup_time("initialize registry");
1906 registry_init();
1907 +
1908 // fork the spawn server
1909 + delta_startup_time("fork the spawn server");
1910 spawn_init();
1911 +
1912 /*
1913 * Libuv uv_spawn() uses SIGCHLD internally:
1914 * https://github.com/libuv/libuv/blob/cc51217a317e96510fbb284721d5e6bc2af31e33/src/unix/process.c#L485
@@ -1837,15 +1921,21 @@ int main(int argc, char **argv) {
1921 // ------------------------------------------------------------------------
1922 // initialize rrd, registry, health, rrdpush, etc.
1923
1924 + delta_startup_time("collecting system info");
1925 +
1926 netdata_anonymous_statistics_enabled=-1;
1927 struct rrdhost_system_info *system_info = callocz(1, sizeof(struct rrdhost_system_info));
1928 get_system_info(system_info);
1929 system_info->hops = 0;
1930 get_install_type(&system_info->install_type, &system_info->prebuilt_arch, &system_info->prebuilt_dist);
1931
1932 + delta_startup_time("initialize RRD structures");
1933 +
1934 if(rrd_init(netdata_configured_hostname, system_info, false))
1935 fatal("Cannot initialize localhost instance with name '%s'.", netdata_configured_hostname);
1936
1937 + delta_startup_time("check for incomplete shutdown");
1938 +
1939 char agent_crash_file[FILENAME_MAX + 1];
1940 char agent_incomplete_shutdown_file[FILENAME_MAX + 1];
1941 snprintfz(agent_incomplete_shutdown_file, FILENAME_MAX, "%s/.agent_incomplete_shutdown", netdata_configured_varlib_dir);
@@ -1860,6 +1950,8 @@ int main(int argc, char **argv) {
1950 // ------------------------------------------------------------------------
1951 // Claim netdata agent to a cloud endpoint
1952
1953 + delta_startup_time("collect claiming info");
1954 +
1955 if (claiming_pending_arguments)
1956 claim_agent(claiming_pending_arguments);
1957 load_claiming_state();
@@ -1870,11 +1962,14 @@ int main(int argc, char **argv) {
1962 error_log_limit_reset();
1963
1964 // Load host labels
1965 + delta_startup_time("collect host labels");
1966 reload_host_labels();
1967
1968 // ------------------------------------------------------------------------
1969 // spawn the threads
1970
1971 + delta_startup_time("start the static threads");
1972 +
1973 web_server_config_options();
1974
1975 netdata_zero_metrics_enabled = config_get_boolean_ondemand(CONFIG_SECTION_DB, "enable zero metrics", CONFIG_BOOLEAN_NO);
@@ -1895,9 +1990,14 @@ int main(int argc, char **argv) {
1990 // ------------------------------------------------------------------------
1991 // Initialize netdata agent command serving from cli and signals
1992
1993 + delta_startup_time("initialize commands API");
1994 +
1995 commands_init();
1996
1900 - info("netdata initialization completed. Enjoy real-time performance monitoring!");
1997 + delta_startup_time("ready");
1998 +
1999 + usec_t ready_ut = now_monotonic_usec();
2000 + info("NETDATA STARTUP: completed in %llu ms. Enjoy real-time performance monitoring!", (ready_ut - started_ut) / USEC_PER_MS);
2001 netdata_ready = 1;
2002
2003 send_statistics("START", "-", "-");