summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@zresearch.com>2009-04-01 14:01:05 -0700
committerAnand V. Avati <avati@amp.gluster.com>2009-04-02 19:19:29 +0530
commit9f2ef60274dae8b302d691ba8d266cd76dcd7c4b (patch)
tree18eda89f71258fa4b631faa9e38dd09d8c2e04ee
parentb1bbd77f16a13f8109d1e2e1b4ed869db1e86645 (diff)
io-threads: Support autoscaling volfile options
This commit finally makes the autoscaling feature visible to the user. Know that we're now using two separate thread-pools, one for data requests, called ordered thread-pool in io-threads, and the other for meta-data requests, called un-ordered thread-pool. We do not expose this information to the user to keep io-threads simple. Consequently, when the user specifies a min-threads and max-threads value, the number of threads assigned to each pool is equal, i.e. both pools start with their min threads set to half of the option "min-threads" and both scale up their threads at most up to half of option "max-threads". Volfile options will be added to the wiki and user-guide. Signed-off-by: Anand V. Avati <avati@amp.gluster.com>
-rw-r--r--xlators/performance/io-threads/src/io-threads.c120
-rw-r--r--xlators/performance/io-threads/src/io-threads.h8
2 files changed, 104 insertions, 24 deletions
diff --git a/xlators/performance/io-threads/src/io-threads.c b/xlators/performance/io-threads/src/io-threads.c
index 31d86f5e7..986215299 100644
--- a/xlators/performance/io-threads/src/io-threads.c
+++ b/xlators/performance/io-threads/src/io-threads.c
@@ -1777,8 +1777,12 @@ workers_init (iot_conf_t *conf)
int32_t
init (xlator_t *this)
{
- iot_conf_t *conf;
- dict_t *options = this->options;
+ iot_conf_t *conf = NULL;
+ dict_t *options = this->options;
+ int thread_count = IOT_MIN_THREADS;
+ gf_boolean_t autoscaling = IOT_SCALING_OFF;
+ char *scalestr = NULL;
+ int min_threads, max_threads;
if (!this->children || this->children->next) {
gf_log ("io-threads",
@@ -1795,33 +1799,96 @@ init (xlator_t *this)
conf = (void *) CALLOC (1, sizeof (*conf));
ERR_ABORT (conf);
- conf->thread_count = 1;
+ if ((dict_get_str (options, "autoscaling", &scalestr)) == 0) {
+ if ((gf_string2boolean (scalestr, &autoscaling)) == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "'autoscaling' option must be"
+ " boolean");
+ return -1;
+ }
+ }
if (dict_get (options, "thread-count")) {
- conf->thread_count = data_to_int32 (dict_get (options,
- "thread-count"));
- gf_log ("io-threads",
- GF_LOG_DEBUG,
- "Using conf->thread_count = %d",
- conf->thread_count);
- }
+ thread_count = data_to_int32 (dict_get (options,
+ "thread-count"));
+ if (scalestr != NULL)
+ gf_log (this->name, GF_LOG_WARNING,
+ "'thread-count' is specified with "
+ "'autoscaling' on. Ignoring"
+ "'thread-count' option.");
+ if (thread_count < 2)
+ thread_count = 2;
+ }
+
+ min_threads = IOT_MIN_THREADS;
+ max_threads = IOT_MAX_THREADS;
+ if (dict_get (options, "min-threads"))
+ min_threads = data_to_int32 (dict_get (options,
+ "min-threads"));
+
+ if (dict_get (options, "max-threads"))
+ max_threads = data_to_int32 (dict_get (options,
+ "max-threads"));
+
+ if (min_threads > max_threads) {
+ gf_log (this->name, GF_LOG_ERROR, " min-threads must be less "
+ "than max-threads");
+ return -1;
+ }
- /* Init params for un-ordered workers. These should be got from
- * the volfile options.
+ /* If autoscaling is off, then adjust the min and max
+ * threads according to thread-count.
+ * This is based on the assumption that despite autoscaling
+ * being off, we still want to have separate pools for data
+ * and meta-data threads.
*/
+ if (!autoscaling)
+ max_threads = min_threads = thread_count;
+
+ /* If user specifies an odd number of threads, increase it by
+ * one. The reason for having an even number of threads is
+ * explained later.
+ */
+ if (max_threads % 2)
+ max_threads++;
+
+ if(min_threads % 2)
+ min_threads++;
+
+ /* If the user wants to have only a single thread for
+ * some strange reason, make sure we set this count to
+ * 2. Explained later.
+ */
+ if (min_threads < 2)
+ min_threads = 2;
+
+ /* Again, have atleast two. Read on. */
+ if (max_threads < 2)
+ max_threads = 2;
+
+ /* This is why we need atleast two threads.
+ * We're dividing the specified thread pool into
+ * 2 halves, equally between ordered and unordered
+ * pools.
+ */
+
+ /* Init params for un-ordered workers. */
pthread_mutex_init (&conf->utlock, NULL);
- conf->max_u_threads = IOT_MAX_THREADS;
- conf->min_u_threads = IOT_MIN_THREADS;
+ conf->max_u_threads = max_threads / 2;
+ conf->min_u_threads = min_threads / 2;
conf->u_idle_time = IOT_DEFAULT_IDLE;
- conf->u_scaling = IOT_SCALING_OFF;
+ conf->u_scaling = autoscaling;
/* Init params for ordered workers. */
pthread_mutex_init (&conf->otlock, NULL);
- conf->max_o_threads = IOT_MAX_THREADS;
- conf->min_o_threads = IOT_MIN_THREADS;
+ conf->max_o_threads = max_threads / 2;
+ conf->min_o_threads = min_threads / 2;
conf->o_idle_time = IOT_DEFAULT_IDLE;
- conf->o_scaling = IOT_SCALING_OFF;
+ conf->o_scaling = autoscaling;
+ gf_log (this->name, GF_LOG_DEBUG, "io-threads: Autoscaling: %s, "
+ "min_threads: %d, max_threads: %d",
+ (autoscaling) ? "on":"off", min_threads, max_threads);
conf->this = this;
workers_init (conf);
@@ -1885,8 +1952,21 @@ struct xlator_cbks cbks = {
struct volume_options options[] = {
{ .key = {"thread-count"},
.type = GF_OPTION_TYPE_INT,
- .min = 1,
- .max = 32
+ .min = IOT_MIN_THREADS,
+ .max = IOT_MAX_THREADS
},
+ { .key = {"autoscaling"},
+ .type = GF_OPTION_TYPE_BOOL
+ },
+ { .key = {"min-threads"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = IOT_MIN_THREADS,
+ .max = IOT_MAX_THREADS
+ },
+ { .key = {"max-threads"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = IOT_MIN_THREADS,
+ .max = IOT_MAX_THREADS
+ },
{ .key = {NULL} },
};
diff --git a/xlators/performance/io-threads/src/io-threads.h b/xlators/performance/io-threads/src/io-threads.h
index a613884da..3bc37a67d 100644
--- a/xlators/performance/io-threads/src/io-threads.h
+++ b/xlators/performance/io-threads/src/io-threads.h
@@ -60,8 +60,8 @@ struct iot_request {
#define IOT_MIN_THREADS 32
#define IOT_MAX_THREADS 512
-#define IOT_SCALING_OFF 1
-#define IOT_SCALING_ON 2
+#define IOT_SCALING_OFF _gf_false
+#define IOT_SCALING_ON _gf_true
#define iot_ordered_scaling_on(conf) ((conf)->o_scaling == IOT_SCALING_ON)
#define iot_unordered_scaling_on(conf) ((conf)->u_scaling == IOT_SCALING_ON)
@@ -103,7 +103,7 @@ struct iot_conf {
int o_idle_time; /* in Secs. The idle time after which an
ordered thread exits.
*/
- int o_scaling; /* Set to IOT_SCALING_OFF if user does not want
+ gf_boolean_t o_scaling; /* Set to IOT_SCALING_OFF if user does not want
thread scaling on ordered threads.
If scaling is off, io-threads maintains
at least min_o_threads number of threads
@@ -124,7 +124,7 @@ struct iot_conf {
request for this amount of secs, it should
try to die.
*/
- int u_scaling; /* Set to IOT_SCALING_OFF if user does not want
+ gf_boolean_t u_scaling; /* Set to IOT_SCALING_OFF if user does not want
thread scaling on unordered threads.
If scaling is off, io-threads maintains
at least min_u_threads number of threads