Commit d6bac7db authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#58226 Some InnoDB debug checks consume too much CPU time

Do not disable InnoDB inlining when UNIV_DEBUG is defined. The
inlining is now solely controlled by the preprocessor symbol
UNIV_MUST_NOT_INLINE and by any compiler options.

mtr_memo_contains(): Add an explicit type conversion from void*, so
that the function can be compiled by a C++ compiler. Previously, this
function was never seen by the C++ compiler, because it is only
present in UNIV_DEBUG builds and InnoDB inlining used to be disabled.

buf_flush_validate_skip(): A wrapper that skips most calls of
buf_flush_validate_low(). Invoked by debug assertions in
buf_flush_insert_into_flush_list() and buf_flush_remove().

fil_validate_skip(): A wrapper that skips most calls of
fil_validate(). Invoked by debug assertions in fil_io() and fil_io_wait().

os_aio_validate_skip(): A wrapper that skips most calls of
os_aio_validate(). Invoked by debug assertions in
os_aio_func(), os_aio_windows_handle() and os_aio_simulated_handle.

os_get_os_version(): Only include this function if __WIN__ is defined.

sync_array_deadlock_step(): Slight optimizations. This function is a
major CPU consumer in UNIV_SYNC_DEBUG builds.
parent 2a4aca3e
...@@ -88,6 +88,34 @@ ibool ...@@ -88,6 +88,34 @@ ibool
buf_flush_validate_low( buf_flush_validate_low(
/*===================*/ /*===================*/
buf_pool_t* buf_pool); /*!< in: Buffer pool instance */ buf_pool_t* buf_pool); /*!< in: Buffer pool instance */
/******************************************************************//**
Validates the flush list some of the time.
@return TRUE if ok or the check was skipped */
static
ibool
buf_flush_validate_skip(
/*====================*/
buf_pool_t* buf_pool) /*!< in: Buffer pool instance */
{
/** Try buf_flush_validate_low() every this many times */
# define BUF_FLUSH_VALIDATE_SKIP 23
/** The buf_flush_validate_low() call skip counter.
Use a signed type because of the race condition below. */
static int buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
/* There is a race condition below, but it does not matter,
because this call is only for heuristic purposes. We want to
reduce the call frequency of the costly buf_flush_validate_low()
check in debug builds. */
if (--buf_flush_validate_count > 0) {
return(TRUE);
}
buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
return(buf_flush_validate_low(buf_pool));
}
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//** /******************************************************************//**
...@@ -293,7 +321,7 @@ buf_flush_insert_into_flush_list( ...@@ -293,7 +321,7 @@ buf_flush_insert_into_flush_list(
} }
#endif /* UNIV_DEBUG_VALGRIND */ #endif /* UNIV_DEBUG_VALGRIND */
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low(buf_pool)); ut_a(buf_flush_validate_skip(buf_pool));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_flush_list_mutex_exit(buf_pool); buf_flush_list_mutex_exit(buf_pool);
...@@ -515,7 +543,7 @@ buf_flush_remove( ...@@ -515,7 +543,7 @@ buf_flush_remove(
bpage->oldest_modification = 0; bpage->oldest_modification = 0;
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low(buf_pool)); ut_a(buf_flush_validate_skip(buf_pool));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_flush_list_mutex_exit(buf_pool); buf_flush_list_mutex_exit(buf_pool);
......
...@@ -299,6 +299,34 @@ struct fil_system_struct { ...@@ -299,6 +299,34 @@ struct fil_system_struct {
initialized. */ initialized. */
static fil_system_t* fil_system = NULL; static fil_system_t* fil_system = NULL;
#ifdef UNIV_DEBUG
/** Try fil_validate() every this many times */
# define FIL_VALIDATE_SKIP 17
/******************************************************************//**
Checks the consistency of the tablespace cache some of the time.
@return TRUE if ok or the check was skipped */
static
ibool
fil_validate_skip(void)
/*===================*/
{
/** The fil_validate() call skip counter. Use a signed type
because of the race condition below. */
static int fil_validate_count = FIL_VALIDATE_SKIP;
/* There is a race condition below, but it does not matter,
because this call is only for heuristic purposes. We want to
reduce the call frequency of the costly fil_validate() check
in debug builds. */
if (--fil_validate_count > 0) {
return(TRUE);
}
fil_validate_count = FIL_VALIDATE_SKIP;
return(fil_validate());
}
#endif /* UNIV_DEBUG */
/********************************************************************//** /********************************************************************//**
NOTE: you must call fil_mutex_enter_and_prepare_for_io() first! NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
...@@ -4307,7 +4335,7 @@ fil_io( ...@@ -4307,7 +4335,7 @@ fil_io(
#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE #if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE" # error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
#endif #endif
ut_ad(fil_validate()); ut_ad(fil_validate_skip());
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
# ifndef UNIV_LOG_DEBUG # ifndef UNIV_LOG_DEBUG
/* ibuf bitmap pages must be read in the sync aio mode: */ /* ibuf bitmap pages must be read in the sync aio mode: */
...@@ -4466,7 +4494,7 @@ fil_io( ...@@ -4466,7 +4494,7 @@ fil_io(
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
ut_ad(fil_validate()); ut_ad(fil_validate_skip());
} }
return(DB_SUCCESS); return(DB_SUCCESS);
...@@ -4490,7 +4518,7 @@ fil_aio_wait( ...@@ -4490,7 +4518,7 @@ fil_aio_wait(
void* message; void* message;
ulint type; ulint type;
ut_ad(fil_validate()); ut_ad(fil_validate_skip());
if (srv_use_native_aio) { if (srv_use_native_aio) {
srv_set_io_thread_op_info(segment, "native aio handle"); srv_set_io_thread_op_info(segment, "native aio handle");
...@@ -4521,7 +4549,7 @@ fil_aio_wait( ...@@ -4521,7 +4549,7 @@ fil_aio_wait(
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
ut_ad(fil_validate()); ut_ad(fil_validate_skip());
/* Do the i/o handling */ /* Do the i/o handling */
/* IMPORTANT: since i/o handling for reads will read also the insert /* IMPORTANT: since i/o handling for reads will read also the insert
......
...@@ -160,7 +160,7 @@ mtr_memo_contains( ...@@ -160,7 +160,7 @@ mtr_memo_contains(
while (offset > 0) { while (offset > 0) {
offset -= sizeof(mtr_memo_slot_t); offset -= sizeof(mtr_memo_slot_t);
slot = dyn_array_get_element(memo, offset); slot = (mtr_memo_slot_t*) dyn_array_get_element(memo, offset);
if ((object == slot->object) && (type == slot->type)) { if ((object == slot->object) && (type == slot->type)) {
......
...@@ -373,6 +373,7 @@ typedef HANDLE os_file_dir_t; /*!< directory stream */ ...@@ -373,6 +373,7 @@ typedef HANDLE os_file_dir_t; /*!< directory stream */
typedef DIR* os_file_dir_t; /*!< directory stream */ typedef DIR* os_file_dir_t; /*!< directory stream */
#endif #endif
#ifdef __WIN__
/***********************************************************************//** /***********************************************************************//**
Gets the operating system version. Currently works only on Windows. Gets the operating system version. Currently works only on Windows.
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA, @return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
...@@ -381,6 +382,7 @@ UNIV_INTERN ...@@ -381,6 +382,7 @@ UNIV_INTERN
ulint ulint
os_get_os_version(void); os_get_os_version(void);
/*===================*/ /*===================*/
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/****************************************************************//** /****************************************************************//**
Creates the seek mutexes used in positioned reads and writes. */ Creates the seek mutexes used in positioned reads and writes. */
......
...@@ -253,7 +253,7 @@ easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */ ...@@ -253,7 +253,7 @@ easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */
# define UNIV_INTERN # define UNIV_INTERN
#endif #endif
#if (!defined(UNIV_DEBUG) && !defined(UNIV_MUST_NOT_INLINE)) #ifndef UNIV_MUST_NOT_INLINE
/* Definition for inline version */ /* Definition for inline version */
#ifdef __WIN__ #ifdef __WIN__
......
...@@ -302,6 +302,36 @@ UNIV_INTERN ulint os_n_pending_writes = 0; ...@@ -302,6 +302,36 @@ UNIV_INTERN ulint os_n_pending_writes = 0;
/** Number of pending read operations */ /** Number of pending read operations */
UNIV_INTERN ulint os_n_pending_reads = 0; UNIV_INTERN ulint os_n_pending_reads = 0;
#ifdef UNIV_DEBUG
/**********************************************************************//**
Validates the consistency the aio system some of the time.
@return TRUE if ok or the check was skipped */
UNIV_INTERN
ibool
os_aio_validate_skip(void)
/*======================*/
{
/** Try os_aio_validate() every this many times */
# define OS_AIO_VALIDATE_SKIP 13
/** The os_aio_validate() call skip counter.
Use a signed type because of the race condition below. */
static int os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
/* There is a race condition below, but it does not matter,
because this call is only for heuristic purposes. We want to
reduce the call frequency of the costly os_aio_validate()
check in debug builds. */
if (--os_aio_validate_count > 0) {
return(TRUE);
}
os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
return(os_aio_validate());
}
#endif /* UNIV_DEBUG */
#ifdef __WIN__
/***********************************************************************//** /***********************************************************************//**
Gets the operating system version. Currently works only on Windows. Gets the operating system version. Currently works only on Windows.
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA, @return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
...@@ -311,7 +341,6 @@ ulint ...@@ -311,7 +341,6 @@ ulint
os_get_os_version(void) os_get_os_version(void)
/*===================*/ /*===================*/
{ {
#ifdef __WIN__
OSVERSIONINFO os_info; OSVERSIONINFO os_info;
os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
...@@ -340,12 +369,8 @@ os_get_os_version(void) ...@@ -340,12 +369,8 @@ os_get_os_version(void)
ut_error; ut_error;
return(0); return(0);
} }
#else
ut_error;
return(0);
#endif
} }
#endif /* __WIN__ */
/***********************************************************************//** /***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function. Retrieves the last error number if an error occurs in a file io function.
...@@ -4008,7 +4033,7 @@ os_aio_func( ...@@ -4008,7 +4033,7 @@ os_aio_func(
ut_ad(n > 0); ut_ad(n > 0);
ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(os_aio_validate()); ut_ad(os_aio_validate_skip());
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
ut_ad((n & 0xFFFFFFFFUL) == n); ut_ad((n & 0xFFFFFFFFUL) == n);
#endif #endif
...@@ -4210,7 +4235,7 @@ os_aio_windows_handle( ...@@ -4210,7 +4235,7 @@ os_aio_windows_handle(
/* NOTE! We only access constant fields in os_aio_array. Therefore /* NOTE! We only access constant fields in os_aio_array. Therefore
we do not have to acquire the protecting mutex yet */ we do not have to acquire the protecting mutex yet */
ut_ad(os_aio_validate()); ut_ad(os_aio_validate_skip());
ut_ad(segment < array->n_segments); ut_ad(segment < array->n_segments);
n = array->n_slots / array->n_segments; n = array->n_slots / array->n_segments;
...@@ -4630,7 +4655,7 @@ os_aio_simulated_handle( ...@@ -4630,7 +4655,7 @@ os_aio_simulated_handle(
srv_set_io_thread_op_info(global_segment, srv_set_io_thread_op_info(global_segment,
"looking for i/o requests (a)"); "looking for i/o requests (a)");
ut_ad(os_aio_validate()); ut_ad(os_aio_validate_skip());
ut_ad(segment < array->n_segments); ut_ad(segment < array->n_segments);
n = array->n_slots / array->n_segments; n = array->n_slots / array->n_segments;
......
...@@ -590,9 +590,6 @@ sync_array_deadlock_step( ...@@ -590,9 +590,6 @@ sync_array_deadlock_step(
ulint depth) /*!< in: recursion depth */ ulint depth) /*!< in: recursion depth */
{ {
sync_cell_t* new; sync_cell_t* new;
ibool ret;
depth++;
if (pass != 0) { if (pass != 0) {
/* If pass != 0, then we do not know which threads are /* If pass != 0, then we do not know which threads are
...@@ -604,7 +601,7 @@ sync_array_deadlock_step( ...@@ -604,7 +601,7 @@ sync_array_deadlock_step(
new = sync_array_find_thread(arr, thread); new = sync_array_find_thread(arr, thread);
if (new == start) { if (UNIV_UNLIKELY(new == start)) {
/* Stop running of other threads */ /* Stop running of other threads */
ut_dbg_stop_threads = TRUE; ut_dbg_stop_threads = TRUE;
...@@ -616,11 +613,7 @@ sync_array_deadlock_step( ...@@ -616,11 +613,7 @@ sync_array_deadlock_step(
return(TRUE); return(TRUE);
} else if (new) { } else if (new) {
ret = sync_array_detect_deadlock(arr, start, new, depth); return(sync_array_detect_deadlock(arr, start, new, depth + 1));
if (ret) {
return(TRUE);
}
} }
return(FALSE); return(FALSE);
} }
......
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