Commit 5f79ed02 authored by vasil's avatar vasil

branches/zip:

Enable functionality to have multiple background io helper threads.
This patch is based on percona contributions.

More details about this patch will be written at:
https://svn.innodb.com/innobase/MultipleBackgroundThreads

The patch essentially does the following:

expose following knobs:
innodb_read_io_threads = [1 - 64] default 1
innodb_write_io_threads = [1 - 64] default 1

deprecate innodb_file_io_threads (this parameter was relevant only on windows)

Internally it allows multiple segments for read and write IO request arrays
where one thread works on one segement.

Submitted by:	Inaam (rb://124)
Approved by:	Heikki (rb://124)
parent b100a45f
......@@ -124,6 +124,8 @@ static long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_force_recovery, innobase_open_files,
innobase_autoinc_lock_mode;
static ulong innobase_commit_concurrency = 0;
static ulong innobase_read_io_threads;
static ulong innobase_write_io_threads;
static long long innobase_buffer_pool_size, innobase_log_file_size;
......@@ -2128,6 +2130,8 @@ innobase_change_buffering_inited_ok:
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
srv_force_recovery = (ulint) innobase_force_recovery;
......@@ -9652,6 +9656,16 @@ static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
"Number of file I/O threads in InnoDB.",
NULL, NULL, 4, 4, 64, 0);
static MYSQL_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of background read I/O threads in InnoDB.",
NULL, NULL, 1, 1, 64, 0);
static MYSQL_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of background write I/O threads in InnoDB.",
NULL, NULL, 1, 1, 64, 0);
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Helps to save your data in case the disk image of the database becomes corrupt.",
......@@ -9755,6 +9769,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(doublewrite),
MYSQL_SYSVAR(fast_shutdown),
MYSQL_SYSVAR(file_io_threads),
MYSQL_SYSVAR(read_io_threads),
MYSQL_SYSVAR(write_io_threads),
MYSQL_SYSVAR(file_per_table),
MYSQL_SYSVAR(file_format),
MYSQL_SYSVAR(file_format_check),
......
......@@ -574,23 +574,23 @@ ibool
os_file_create_subdirs_if_needed(
/*=============================*/
const char* path); /*!< in: path name */
/************************************************************************//**
Initializes the asynchronous io system. Creates separate aio array for
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
segment, two aio arrays for log reads and writes with one segment, and a
synchronous aio array of the specified size. The combined number of segments
in the three first aio arrays is the parameter n_segments given to the
function. The caller must create an i/o handler thread for each segment in
the four first arrays, but not for the sync aio array. */
/***********************************************************************
Initializes the asynchronous io system. Creates one array each for ibuf
and log i/o. Also creates one array each for read and write where each
array is divided logically into n_read_segs and n_write_segs
respectively. The caller must create an i/o handler thread for each
segment in these arrays. This function also creates the sync array.
No i/o handler thread needs to be created for that */
UNIV_INTERN
void
os_aio_init(
/*========*/
ulint n, /*!< in: maximum number of pending aio operations
allowed; n must be divisible by n_segments */
ulint n_segments, /*!< in: combined number of segments in the four
first aio arrays; must be >= 4 */
ulint n_slots_sync); /*!< in: number of slots in the sync aio array */
ulint n_per_seg, /*<! in: maximum number of pending aio
operations allowed per segment */
ulint n_read_segs, /*<! in: number of reader threads */
ulint n_write_segs, /*<! in: number of writer threads */
ulint n_slots_sync); /*<! in: number of slots in the sync aio
array */
/*******************************************************************//**
Requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
......
......@@ -126,6 +126,8 @@ extern ulint srv_lock_table_size;
extern ulint srv_n_file_io_threads;
extern ulint srv_read_ahead_factor;
extern ulint srv_n_read_io_threads;
extern ulint srv_n_write_io_threads;
#ifdef UNIV_LOG_ARCHIVE
extern ibool srv_log_archive_on;
......@@ -218,7 +220,7 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
same DRAM page as other hotspot semaphores */
#define kernel_mutex (*kernel_mutex_temp)
#define SRV_MAX_N_IO_THREADS 100
#define SRV_MAX_N_IO_THREADS 130
/* Array of English strings describing the current state of an
i/o handler thread */
......
......@@ -2923,31 +2923,27 @@ os_aio_array_create(
return(array);
}
/************************************************************************//**
Initializes the asynchronous io system. Calls also os_io_init_simple.
Creates a separate aio array for
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
segment, two aio arrays for log reads and writes with one segment, and a
synchronous aio array of the specified size. The combined number of segments
in the three first aio arrays is the parameter n_segments given to the
function. The caller must create an i/o handler thread for each segment in
the four first arrays, but not for the sync aio array. */
/***********************************************************************
Initializes the asynchronous io system. Creates one array each for ibuf
and log i/o. Also creates one array each for read and write where each
array is divided logically into n_read_segs and n_write_segs
respectively. The caller must create an i/o handler thread for each
segment in these arrays. This function also creates the sync array.
No i/o handler thread needs to be created for that */
UNIV_INTERN
void
os_aio_init(
/*========*/
ulint n, /*!< in: maximum number of pending aio operations
allowed; n must be divisible by n_segments */
ulint n_segments, /*!< in: combined number of segments in the four
first aio arrays; must be >= 4 */
ulint n_slots_sync) /*!< in: number of slots in the sync aio array */
ulint n_per_seg, /*<! in: maximum number of pending aio
operations allowed per segment */
ulint n_read_segs, /*<! in: number of reader threads */
ulint n_write_segs, /*<! in: number of writer threads */
ulint n_slots_sync) /*<! in: number of slots in the sync aio
array */
{
ulint n_read_segs;
ulint n_write_segs;
ulint n_per_seg;
ulint i;
ulint n_segments = 2 + n_read_segs + n_write_segs;
ut_ad(n % n_segments == 0);
ut_ad(n_segments >= 4);
os_io_init_simple();
......@@ -2956,9 +2952,6 @@ os_aio_init(
srv_set_io_thread_op_info(i, "not started yet");
}
n_per_seg = n / n_segments;
n_write_segs = (n_segments - 2) / 2;
n_read_segs = n_segments - 2 - n_write_segs;
/* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
......@@ -3157,6 +3150,18 @@ os_aio_array_reserve_slot(
OVERLAPPED* control;
#endif
ulint i;
ulint slots_per_seg;
ulint local_seg;
/* No need of a mutex. Only reading constant fields */
slots_per_seg = array->n_slots / array->n_segments;
/* We attempt to keep adjacent blocks in the same local
segment. This can help in merging IO requests when we are
doing simulated AIO */
local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
% array->n_segments;
loop:
os_mutex_enter(array->mutex);
......@@ -3175,14 +3180,26 @@ loop:
goto loop;
}
/* First try to find a slot in the preferred local segment */
for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
slot = os_aio_array_get_nth_slot(array, i);
if (slot->reserved == FALSE) {
goto found;
}
}
/* Fall back to a full scan. We are guaranteed to find a slot */
for (i = 0;; i++) {
slot = os_aio_array_get_nth_slot(array, i);
if (slot->reserved == FALSE) {
break;
goto found;
}
}
found:
ut_a(slot->reserved == FALSE);
array->n_reserved++;
if (array->n_reserved == 1) {
......
......@@ -173,7 +173,11 @@ UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
/* This parameter is deprecated. Use srv_n_io_[read|write]_threads
instead. */
UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
/* User settable value of the number of pages that InnoDB will tolerate
within a 64 page extent even if they are accessed out of order or have
......
......@@ -1007,6 +1007,7 @@ innobase_start_or_create_for_mysql(void)
ulint tablespace_size_in_header;
ulint err;
ulint i;
ulint io_limit;
my_bool srv_file_per_table_original_value
= srv_file_per_table;
mtr_t mtr;
......@@ -1265,27 +1266,35 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
/* Restrict the maximum number of file i/o threads */
if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
srv_n_file_io_threads = SRV_MAX_N_IO_THREADS;
/* If user has set the value of innodb_file_io_threads then
we'll emit a message telling the user that this parameter
is now deprecated. */
if (srv_n_file_io_threads != 4) {
fprintf(stderr, "InnoDB: Warning:"
" innodb_file_io_threads is deprecated."
" Please use innodb_read_io_threads and"
" innodb_write_io_threads instead\n");
}
if (!os_aio_use_native_aio) {
/* In simulated aio we currently have use only for 4 threads */
srv_n_file_io_threads = 4;
/* Now overwrite the value on srv_n_file_io_threads */
srv_n_file_io_threads = 2 + srv_n_read_io_threads
+ srv_n_write_io_threads;
ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS);
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
* srv_n_file_io_threads,
srv_n_file_io_threads,
SRV_MAX_N_PENDING_SYNC_IOS);
/* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit
still applies to windows. */
if (!os_aio_use_native_aio) {
io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD;
} else {
os_aio_init(SRV_N_PENDING_IOS_PER_THREAD
* srv_n_file_io_threads,
srv_n_file_io_threads,
SRV_MAX_N_PENDING_SYNC_IOS);
io_limit = SRV_N_PENDING_IOS_PER_THREAD;
}
os_aio_init(io_limit,
srv_n_read_io_threads,
srv_n_write_io_threads,
SRV_MAX_N_PENDING_SYNC_IOS);
fil_init(srv_file_per_table ? 50000 : 5000,
srv_max_n_open_files);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment