From: kevin.lewis Date: September 7 2012 8:37pm Subject: bzr push into mysql-trunk branch (kevin.lewis:4445 to 4446) Bug#14551372 List-Archive: http://lists.mysql.com/commits/144709 X-Bug: 14551372 Message-Id: <20120907203730.46214.8892.4446@dhcp-adc-twvpn-3-vpnpool-10-154-97-89.vpn.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4446 kevin.lewis@stripped 2012-09-07 Bug#14551372 - INNODB: UNIV_SYNC_DEBUG SYNC ARRAY IS NOT OPTIMIZED As part of the investigation into Bug 14520559 (LARGE BLOB INSERTS ARE SLOW AND TROUBLESOME), I found that the sync array that is used under UNIV_SYNC_DEBUG will store the same level-latch pair over and over when the latch is recursively locked. The maximum size of this sync array was hit when running innodb_bug13450566.test with a 4k page size because seven different latches were being locked recursively over and over. This filled up the available 10,000 slots in the array and an assert was hit. When the assert happened, there were actually only 14 unique latches being tracked for that thread. This patch add a count field to each slot in this sync array. The count is > 1 for recursive locking. This reduces the actual array size tremendously and can help performance when using UNIV_SYNC_DEBUG as well as prevent this 'array full' assert when a lot of recursive locking is happening. This will require an extra search through the array to find the previous latch-level slot, but that is offset when it searches only tens of slots instead of thousands of slots. Approved by Sunny in http://bur03.no.oracle.com/rb/r/1247/ modified: storage/innobase/sync/sync0sync.cc 4445 Marc Alff 2012-09-07 [merge] Merge mysql-5.6 --> mysql-trunk modified: mysql-test/suite/perfschema/r/func_file_io.result mysql-test/suite/perfschema/r/func_mutex.result mysql-test/suite/perfschema/t/func_file_io.test mysql-test/suite/perfschema/t/func_mutex.test === modified file 'storage/innobase/sync/sync0sync.cc' --- a/storage/innobase/sync/sync0sync.cc revid:marc.alff@stripped +++ b/storage/innobase/sync/sync0sync.cc revid:kevin.lewis@stripped @@ -250,6 +250,9 @@ struct sync_level_t{ latch == NULL then this will contain the ordinal value of the next free element */ + ulint count; /*!< Numbe of times this latch has + been locked at this level. Allows + for recursive locking */ }; #endif /* UNIV_SYNC_DEBUG */ @@ -887,6 +890,29 @@ sync_thread_levels_contain( } /******************************************************************//** +Checks if the level value and latch is already stored in the level array. +@return slot if found or NULL */ +static +sync_level_t* +sync_thread_levels_find( +/*====================*/ + sync_arr_t* arr, /*!< in: pointer to level array for an OS + thread */ + void* latch, /*!< in: pointer to a mutex or an rw-lock */ + ulint level) /*!< in: level */ +{ + for (ulint i = 0; i < arr->n_elems; i++) { + sync_level_t* slot = &arr->elems[i]; + + if (slot->latch == latch && slot->level == level) { + return(slot); + } + } + + return(NULL); +} + +/******************************************************************//** Checks if the level array for the current thread contains a mutex or rw-latch at the specified level. @return a matching latch, or NULL if not found */ @@ -1313,6 +1339,16 @@ sync_thread_add_level( } levels_ok: + /* Look for this latch and level in the active list. If it is + already there, then this is a recursive lock. */ + slot = sync_thread_levels_find(array, latch, level); + if (slot != NULL) { + slot->count++; + mutex_exit(&sync_thread_mutex); + return; + } + + /* Get a free slot to track this level and latch */ if (array->next_free == ULINT_UNDEFINED) { ut_a(array->n_elems < array->max_elems); @@ -1333,6 +1369,7 @@ levels_ok: slot->latch = latch; slot->level = level; + slot->count = 1; mutex_exit(&sync_thread_mutex); } @@ -1388,6 +1425,15 @@ sync_thread_reset_level( continue; } + if (slot->count > 1) { + /* Found a latch recursively locked */ + slot->count--; + + mutex_exit(&sync_thread_mutex); + + return(TRUE); + } + slot->latch = NULL; /* Update the free slot list. See comment in sync_level_t No bundle (reason: useless for push emails).