MXS-1360 Add 'thread_stack_size' configuration value

Using the 'thread_stack_size' configuration value, the stack size
of the worker threads can be adjusted.
This commit is contained in:
Johan Wikman 2017-08-14 15:15:41 +03:00
parent e9b2a560b8
commit 49ba1f8fa0
6 changed files with 128 additions and 62 deletions

View File

@ -150,6 +150,16 @@ Additional threads will be created to execute other internal services within
MariaDB MaxScale. This setting is used to configure the number of threads that
will be used to manage the user connections.
#### `thread_stack_size`
This parameter controls the stack size of the worker threads. The default value
is 0, which means that the pthread default will be used. The size can be specified
as explained in detail [here](#sizes).
```
thread_stack_size=5Mi
```
#### `auth_connect_timeout`
The connection timeout in seconds for the MySQL connections to the backend

View File

@ -152,6 +152,7 @@ extern const char CN_SSL_KEY[];
extern const char CN_SSL_VERSION[];
extern const char CN_STRIP_DB_ESC[];
extern const char CN_THREADS[];
extern const char CN_THREAD_STACK_SIZE[];
extern const char CN_TYPE[];
extern const char CN_UNIX[];
extern const char CN_USER[];
@ -189,6 +190,7 @@ typedef struct
{
bool config_check; /**< Only check config */
int n_threads; /**< Number of polling threads */
size_t thread_stack_size; /**< The stack size of each worker thread */
char *version_string; /**< The version string of embedded db library */
char release_string[RELEASE_STR_LENGTH]; /**< The release name string of the system */
char sysname[SYSNAME_LEN]; /**< The OS name of the system */
@ -446,6 +448,14 @@ int config_truth_value(const char *value);
*/
int config_threadcount(void);
/**
* @brief Get thread stack size
*
* @return The configured worker thread stack size.
*/
size_t config_thread_stack_size(void);
/**
* @brief Get number of non-blocking polls
*

View File

@ -132,6 +132,7 @@ const char CN_SSL_KEY[] = "ssl_key";
const char CN_SSL_VERSION[] = "ssl_version";
const char CN_STRIP_DB_ESC[] = "strip_db_esc";
const char CN_THREADS[] = "threads";
const char CN_THREAD_STACK_SIZE[] = "thread_stack_size";
const char CN_TYPE[] = "type";
const char CN_UNIX[] = "unix";
const char CN_USER[] = "user";
@ -163,6 +164,7 @@ static void remove_first_last_char(char* value);
static bool test_regex_string_validity(const char* regex_string, const char* key);
static pcre2_code* compile_regex_string(const char* regex_string, bool jit_enabled,
uint32_t options, uint32_t* output_ovector_size);
static uint64_t get_suffixed_size(const char* value);
int config_get_ifaddr(unsigned char *output);
static int config_get_release_string(char* release);
@ -1068,64 +1070,8 @@ int config_get_integer(const MXS_CONFIG_PARAMETER *params, const char *key)
uint64_t config_get_size(const MXS_CONFIG_PARAMETER *params, const char *key)
{
const char *value = config_get_value_string(params, key);
char *end;
uint64_t size = strtoll(value, &end, 10);
switch (*end)
{
case 'T':
case 't':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL * 1000ULL * 1000ULL;
}
break;
case 'G':
case 'g':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL * 1000ULL;
}
break;
case 'M':
case 'm':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL;
}
break;
case 'K':
case 'k':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL;
}
else
{
size *= 1000ULL;
}
break;
default:
break;
}
return size;
return get_suffixed_size(value);
}
const char* config_get_string(const MXS_CONFIG_PARAMETER *params, const char *key)
@ -1334,6 +1280,11 @@ config_threadcount()
return gateway.n_threads;
}
size_t config_thread_stack_size()
{
return gateway.thread_stack_size;
}
/**
* Return the number of non-blocking polls to be done before a blocking poll
* is issued.
@ -1424,6 +1375,10 @@ handle_global_item(const char *name, const char *value)
gateway.n_threads = MXS_MAX_THREADS;
}
}
else if (strcmp(name, CN_THREAD_STACK_SIZE) == 0)
{
gateway.thread_stack_size = get_suffixed_size(value);
}
else if (strcmp(name, CN_NON_BLOCKING_POLLS) == 0)
{
gateway.n_nbpoll = atoi(value);
@ -1799,6 +1754,17 @@ global_defaults()
gateway.admin_ssl_cert[0] = '\0';
gateway.admin_ssl_ca_cert[0] = '\0';
gateway.thread_stack_size = 0;
pthread_attr_t attr;
if (pthread_attr_init(&attr) == 0)
{
size_t thread_stack_size;
if (pthread_attr_getstacksize(&attr, &thread_stack_size) == 0)
{
gateway.thread_stack_size = thread_stack_size;
}
}
if (version_string != NULL)
{
gateway.version_string = MXS_STRDUP_A(version_string);
@ -3890,6 +3856,7 @@ json_t* config_maxscale_to_json(const char* host)
json_object_set_new(param, "execdir", json_string(get_execdir()));
json_object_set_new(param, "connector_plugindir", json_string(get_connector_plugindir()));
json_object_set_new(param, CN_THREADS, json_integer(config_threadcount()));
json_object_set_new(param, CN_THREAD_STACK_SIZE, json_integer(config_thread_stack_size()));
MXS_CONFIG* cnf = config_get_global_options();
@ -4117,3 +4084,74 @@ static bool test_regex_string_validity(const char* regex_string, const char* key
pcre2_code_free(code);
return rval;
}
/**
* Converts a string into the corresponding value, interpreting
* IEC or SI prefixes used as suffixes appropriately.
*
* @param value A numerical string, possibly suffixed by a IEC
* binary prefix or SI prefix.
*
* @return The corresponding size.
*/
static uint64_t get_suffixed_size(const char* value)
{
char *end;
uint64_t size = strtoll(value, &end, 10);
switch (*end)
{
case 'T':
case 't':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL * 1000ULL * 1000ULL;
}
break;
case 'G':
case 'g':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL * 1000ULL;
}
break;
case 'M':
case 'm':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL * 1024ULL;
}
else
{
size *= 1000ULL * 1000ULL;
}
break;
case 'K':
case 'k':
if ((*(end + 1) == 'i') || (*(end + 1) == 'I'))
{
size *= 1024ULL;
}
else
{
size *= 1000ULL;
}
break;
default:
break;
}
return size;
}

View File

@ -1293,6 +1293,7 @@ int main(int argc, char **argv)
int ini_rval;
intptr_t thread_id;
int n_threads; /*< number of epoll listener threads */
size_t thread_stack_size;
int n_services;
int eno = 0; /*< local variable for errno */
int opt;
@ -2032,12 +2033,13 @@ int main(int argc, char **argv)
/*<
* Start workers. We start from 1, worker 0 will be running in the main thread.
*/
thread_stack_size = config_thread_stack_size();
for (i = 1; i < n_threads; i++)
{
worker = Worker::get(i);
ss_dassert(worker);
if (!worker->start())
if (!worker->start(thread_stack_size))
{
const char* logerr = "Failed to start worker thread.";
print_log_n_stderr(true, true, logerr, logerr, 0);
@ -2061,7 +2063,10 @@ int main(int argc, char **argv)
}
}
MXS_NOTICE("MaxScale started with %d server threads.", config_threadcount());
MXS_NOTICE("MaxScale started with %d worker threads, each with a stack size of %lu bytes.",
n_threads, thread_stack_size);
/**
* Successful start, notify the parent process that it can exit.
*/

View File

@ -241,9 +241,12 @@ public:
* This function will start a new thread, in which the `run`
* function will be executed.
*
* @param stack_size The stack size of the new thread. A value of 0 means
* that the pthread default should be used.
*
* @return True if the thread could be started, false otherwise.
*/
bool start();
bool start(size_t stack_size = 0);
/**
* Waits for the worker to finish.

View File

@ -843,11 +843,11 @@ void Worker::run()
MXS_NOTICE("Worker %d has shut down.", m_id);
}
bool Worker::start()
bool Worker::start(size_t stack_size)
{
m_started = true;
if (!thread_start(&m_thread, &Worker::thread_main, this, 0))
if (!thread_start(&m_thread, &Worker::thread_main, this, stack_size))
{
m_started = false;
}