From 9dbe2d6fee4f11c8db2e5cc4b9b1286e68c95bc3 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Sun, 26 Aug 2018 00:41:37 -0400 Subject: [PATCH] bees: add -G/--thread-min option for minimum thread count The -g option limits the number of worker threads when the target load average is exceeded. On some systems the load normally runs high, and continuous bees operation is required to avoid running out of disk space. Add a -G/--thread-min option to force at least some threads to continue running. Signed-off-by: Zygo Blaxell --- README.md | 7 +++++-- include/crucible/task.h | 3 +++ lib/task.cc | 20 +++++++++++++++++++- src/bees.cc | 14 +++++++++++--- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d065ff7..1186a61 100644 --- a/README.md +++ b/README.md @@ -545,8 +545,11 @@ Command Line Options * --loadavg-target (-g) LOADAVG * Specify load average target for dynamic worker threads. Threads will be started or stopped subject to the upper limit imposed - by thread-factor and thread-count until the load average is within - +/- 0.5 of LOADAVG. + by thread-factor, thread-min and thread-count until the load average + is within +/- 0.5 of LOADAVG. +* --thread-min (-G) COUNT + * Specify minimum number of worker threads for scanning. + Ignored unless -g option is used to specify a target load. * --scan-mode (-m) MODE * Specify extent scanning algorithm. Default mode is 0. diff --git a/include/crucible/task.h b/include/crucible/task.h index 755eae2..ed60181 100644 --- a/include/crucible/task.h +++ b/include/crucible/task.h @@ -58,6 +58,9 @@ namespace crucible { // Blocks until the running thread count reaches this number static void set_thread_count(size_t threads); + // Sets minimum thread count when load average tracking enabled + static void set_thread_min_count(size_t min_threads); + // Calls set_thread_count with default static void set_thread_count(); diff --git a/lib/task.cc b/lib/task.cc index 8a981e4..4bdaeec 100644 --- a/lib/task.cc +++ b/lib/task.cc @@ -43,6 +43,7 @@ namespace crucible { condition_variable m_condvar; list> m_queue; size_t m_thread_max; + size_t m_thread_min = 0; set> m_threads; shared_ptr m_load_tracking_thread; double m_load_target = 0; @@ -56,6 +57,7 @@ namespace crucible { void start_threads_nolock(); void start_stop_threads(); void set_thread_count(size_t thread_max); + void set_thread_min_count(size_t thread_min); void adjust_thread_count(); size_t calculate_thread_count_nolock(); void set_loadavg_target(double target); @@ -269,7 +271,7 @@ namespace crucible { m_thread_target = min(max(0.0, m_thread_target), double(m_configured_thread_max)); // Convert to integer but keep within range - const size_t rv = min(size_t(ceil(m_thread_target)), m_configured_thread_max); + const size_t rv = max(m_thread_min, min(size_t(ceil(m_thread_target)), m_configured_thread_max)); return rv; } @@ -306,6 +308,22 @@ namespace crucible { s_tms->set_thread_count(thread_max); } + void + TaskMasterState::set_thread_min_count(size_t thread_min) + { + unique_lock lock(m_mutex); + m_thread_min = thread_min; + lock.unlock(); + adjust_thread_count(); + start_stop_threads(); + } + + void + TaskMaster::set_thread_min_count(size_t thread_min) + { + s_tms->set_thread_min_count(thread_min); + } + void TaskMasterState::loadavg_thread_fn() { diff --git a/src/bees.cc b/src/bees.cc index 2bf4914..08c3fd7 100644 --- a/src/bees.cc +++ b/src/bees.cc @@ -45,6 +45,7 @@ do_cmd_help(char *argv[]) "\t-h, --help\t\tShow this help\n" "\t-c, --thread-count\tWorker thread count (default CPU count * factor)\n" "\t-C, --thread-factor\tWorker thread factor (default " << BEES_DEFAULT_THREAD_FACTOR << ")\n" + "\t-G, --thread-min\t\tMinimum worker thread count with load average target (default 0)\n" "\t-g, --loadavg-target\t\tTarget load average for worker threads (default is no target)\n" "\t-m, --scan-mode\t\tScanning mode (0..2, default 0)\n" "\t-t, --timestamps\tShow timestamps in log output (default)\n" @@ -653,6 +654,7 @@ bees_main(int argc, char *argv[]) bool chatter_prefix_timestamp = true; double thread_factor = 0; unsigned thread_count = 0; + unsigned thread_min = 0; double load_target = 0; // Parse options @@ -661,18 +663,19 @@ bees_main(int argc, char *argv[]) int option_index = 0; static const struct option long_options[] = { { "thread-factor", required_argument, NULL, 'C' }, + { "thread-min", required_argument, NULL, 'G' }, { "strip-paths", no_argument, NULL, 'P' }, { "no-timestamps", no_argument, NULL, 'T' }, { "thread-count", required_argument, NULL, 'c' }, - { "help", no_argument, NULL, 'h' }, { "loadavg-target", required_argument, NULL, 'g' }, + { "help", no_argument, NULL, 'h' }, { "scan-mode", required_argument, NULL, 'm' }, { "absolute-paths", no_argument, NULL, 'p' }, { "timestamps", no_argument, NULL, 't' }, { "verbose", required_argument, NULL, 'v' }, }; - c = getopt_long(argc, argv, "C:PTc:hg:m:ptv:", long_options, &option_index); + c = getopt_long(argc, argv, "C:G:PTc:hg:m:ptv:", long_options, &option_index); if (-1 == c) { break; } @@ -682,6 +685,9 @@ bees_main(int argc, char *argv[]) case 'C': thread_factor = stod(optarg); break; + case 'G': + thread_min = stoul(optarg); + break; case 'P': crucible::set_relative_path(cwd); break; @@ -748,10 +754,12 @@ bees_main(int argc, char *argv[]) if (load_target != 0) { BEESLOGNOTICE("setting load average target to " << load_target); + BEESLOGNOTICE("setting worker thread pool minimum size to " << thread_min); + TaskMaster::set_thread_min_count(thread_min); } TaskMaster::set_loadavg_target(load_target); - BEESLOGNOTICE("setting worker thread pool maximum size to " << load_target); + BEESLOGNOTICE("setting worker thread pool maximum size to " << thread_count); TaskMaster::set_thread_count(thread_count); // Create a context and start crawlers