From: Marc Alff Date: July 16 2010 1:03am Subject: bzr commit into mysql-trunk-bugfixing branch (marc.alff:3117) Bug#52502 List-Archive: http://lists.mysql.com/commits/113717 X-Bug: 52502 Message-Id: <20100716010311.E4B9145E80@linux-su11.site> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3005058440467022475==" --===============3005058440467022475== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/malff/BZR_TREE/mysql-trunk-bugfixing-cleanup/ based on revid:marc.alff@stripped 3117 Marc Alff 2010-07-15 Bug#52502 Performance schema does not start with large mutex_instance buffers Backport from mysql-next-mr (5.6) to mysql-trunk (5.5) modified: storage/perfschema/pfs_global.h storage/perfschema/pfs_instr.cc storage/perfschema/pfs_instr.h === modified file 'storage/perfschema/pfs_global.h' --- a/storage/perfschema/pfs_global.h 2010-07-16 00:28:52 +0000 +++ b/storage/perfschema/pfs_global.h 2010-07-16 01:03:08 +0000 @@ -31,27 +31,50 @@ void pfs_free(void *ptr); inline uint randomized_index(const void *ptr, uint max_size) { + static uint seed1= 0; + static uint seed2= 0; + uint result; + register intptr value; + if (unlikely(max_size == 0)) return 0; /* - ptr is typically an aligned structure, - so the last bits are not really random, but this has no effect. - Apply a factor A*x to spread - close values of ptr further apart (which helps with arrays), - and to spread values way beyond a typical max_size. - Then, apply a modulo to end within [0, max_size - 1]. - A is big prime numbers, to avoid resonating with max_size, - to have a uniform distribution in [0, max_size - 1]. - The value of A is chosen so that index(ptr) and index(ptr + N) (for arrays) - are likely to be not similar for typical values of max_size - (50, 100, 1000, etc). - In other words, (sizeof(T)*A % max_size) should not be a small number, - to avoid that with 'T array[max_size]', index(array[i]) - and index(array[i + 1]) end up pointing in the same area in [0, max_size - 1]. + ptr is typically an aligned structure, and can be in an array. + - The last bits are not random because of alignment, + so we divide by 8. + - The high bits are mostly constant, especially with 64 bits architectures, + but we keep most of them anyway, by doing computation in intptr. + The high bits are significant depending on where the data is + stored (the data segment, the stack, the heap, ...). + - To spread consecutive cells in an array further, we multiply by + a factor A. This factor should not be too high, which would cause + an overflow and cause loss of randomness (droping the top high bits). + The factor is a prime number, to help spread the distribution. + - To add more noise, and to be more robust if the calling code is + passing a constant value instead of a random identity, + we add the previous results, for hysteresys, with a degree 2 polynom, + X^2 + X + 1. + - Last, a modulo is applied to be within the [0, max_size - 1] range. + Note that seed1 and seed2 are static, and are *not* thread safe, + which is even better. + Effect with arrays: T array[N] + - ptr(i) = & array[i] = & array[0] + i * sizeof(T) + - ptr(i+1) = ptr(i) + sizeof(T). + What we want here, is to have index(i) and index(i+1) fall into + very different areas in [0, max_size - 1], to avoid locality. */ - return static_cast - (((reinterpret_cast (ptr)) * 2166179) % max_size); + value= (reinterpret_cast (ptr)) >> 3; + value*= 1789; + value+= seed2 + seed1 + 1; + + result= (static_cast (value)) % max_size; + + seed2= seed1*seed1; + seed1= result; + + DBUG_ASSERT(result < max_size); + return result; } void pfs_print_error(const char *format, ...); === modified file 'storage/perfschema/pfs_instr.cc' --- a/storage/perfschema/pfs_instr.cc 2010-05-31 15:29:54 +0000 +++ b/storage/perfschema/pfs_instr.cc 2010-07-16 01:03:08 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2009 Sun Microsystems, Inc +/* Copyright (c) 2008, 2010 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -10,8 +10,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ /** @file storage/perfschema/pfs_instr.cc @@ -21,8 +21,8 @@ #include #include "my_global.h" -#include "sql_priv.h" #include "my_sys.h" +#include "pfs.h" #include "pfs_stat.h" #include "pfs_instr.h" #include "pfs_global.h" @@ -411,6 +411,8 @@ void cleanup_instruments(void) thread_instr_class_waits_array= NULL; } +extern "C" +{ static uchar *filename_hash_get_key(const uchar *entry, size_t *length, my_bool) { @@ -425,6 +427,7 @@ static uchar *filename_hash_get_key(cons result= file->m_filename; return const_cast (reinterpret_cast (result)); } +} /** Initialize the file name hash. @@ -451,6 +454,75 @@ void cleanup_file_hash(void) } } +void PFS_scan::init(uint random, uint max_size) +{ + m_pass= 0; + + if (max_size == 0) + { + /* Degenerated case, no buffer */ + m_pass_max= 0; + return; + } + + DBUG_ASSERT(random < max_size); + + if (PFS_MAX_ALLOC_RETRY < max_size) + { + /* + The buffer is big compared to PFS_MAX_ALLOC_RETRY, + scan it only partially. + */ + if (random + PFS_MAX_ALLOC_RETRY < max_size) + { + /* + Pass 1: [random, random + PFS_MAX_ALLOC_RETRY - 1] + Pass 2: not used. + */ + m_pass_max= 1; + m_first[0]= random; + m_last[0]= random + PFS_MAX_ALLOC_RETRY; + m_first[1]= 0; + m_last[1]= 0; + } + else + { + /* + Pass 1: [random, max_size - 1] + Pass 2: [0, ...] + The combined length of pass 1 and 2 is PFS_MAX_ALLOC_RETRY. + */ + m_pass_max= 2; + m_first[0]= random; + m_last[0]= max_size; + m_first[1]= 0; + m_last[1]= PFS_MAX_ALLOC_RETRY - (max_size - random); + } + } + else + { + /* + The buffer is small compared to PFS_MAX_ALLOC_RETRY, + scan it in full in two passes. + Pass 1: [random, max_size - 1] + Pass 2: [0, random - 1] + */ + m_pass_max= 2; + m_first[0]= random; + m_last[0]= max_size; + m_first[1]= 0; + m_last[1]= random; + } + + DBUG_ASSERT(m_first[0] < max_size); + DBUG_ASSERT(m_first[1] < max_size); + DBUG_ASSERT(m_last[1] <= max_size); + DBUG_ASSERT(m_last[1] <= max_size); + /* The combined length of all passes should not exceed PFS_MAX_ALLOC_RETRY. */ + DBUG_ASSERT((m_last[0] - m_first[0]) + + (m_last[1] - m_first[1]) <= PFS_MAX_ALLOC_RETRY); +} + /** Create instrumentation for a mutex instance. @param klass the mutex class @@ -459,17 +531,15 @@ void cleanup_file_hash(void) */ PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity) { - int pass; - uint i= randomized_index(identity, mutex_max); + PFS_scan scan; + uint random= randomized_index(identity, mutex_max); - /* - Pass 1: [random, mutex_max - 1] - Pass 2: [0, mutex_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, mutex_max); + scan.has_pass(); + scan.next_pass()) { - PFS_mutex *pfs= mutex_array + i; - PFS_mutex *pfs_last= mutex_array + mutex_max; + PFS_mutex *pfs= mutex_array + scan.first(); + PFS_mutex *pfs_last= mutex_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) @@ -517,17 +587,15 @@ void destroy_mutex(PFS_mutex *pfs) */ PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity) { - int pass; - uint i= randomized_index(identity, rwlock_max); + PFS_scan scan; + uint random= randomized_index(identity, rwlock_max); - /* - Pass 1: [random, rwlock_max - 1] - Pass 2: [0, rwlock_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, rwlock_max); + scan.has_pass(); + scan.next_pass()) { - PFS_rwlock *pfs= rwlock_array + i; - PFS_rwlock *pfs_last= rwlock_array + rwlock_max; + PFS_rwlock *pfs= rwlock_array + scan.first(); + PFS_rwlock *pfs_last= rwlock_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) @@ -581,17 +649,15 @@ void destroy_rwlock(PFS_rwlock *pfs) */ PFS_cond* create_cond(PFS_cond_class *klass, const void *identity) { - int pass; - uint i= randomized_index(identity, cond_max); + PFS_scan scan; + uint random= randomized_index(identity, cond_max); - /* - Pass 1: [random, cond_max - 1] - Pass 2: [0, cond_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, cond_max); + scan.has_pass(); + scan.next_pass()) { - PFS_cond *pfs= cond_array + i; - PFS_cond *pfs_last= cond_array + cond_max; + PFS_cond *pfs= cond_array + scan.first(); + PFS_cond *pfs_last= cond_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) @@ -639,17 +705,15 @@ void destroy_cond(PFS_cond *pfs) PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, ulong thread_id) { - int pass; - uint i= randomized_index(identity, thread_max); + PFS_scan scan; + uint random= randomized_index(identity, thread_max); - /* - Pass 1: [random, thread_max - 1] - Pass 2: [0, thread_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, thread_max); + scan.has_pass(); + scan.next_pass()) { - PFS_thread *pfs= thread_array + i; - PFS_thread *pfs_last= thread_array + thread_max; + PFS_thread *pfs= thread_array + scan.first(); + PFS_thread *pfs_last= thread_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) @@ -733,7 +797,7 @@ find_or_create_file(PFS_thread *thread, const char *filename, uint len) { PFS_file *pfs; - int pass; + PFS_scan scan; if (! filename_hash_inited) { @@ -806,17 +870,14 @@ search: } /* filename is not constant, just using it for noise on create */ - uint i= randomized_index(filename, file_max); + uint random= randomized_index(filename, file_max); - /* - Pass 1: [random, file_max - 1] - Pass 2: [0, file_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, file_max); + scan.has_pass(); + scan.next_pass()) { - pfs= file_array + i; - PFS_file *pfs_last= file_array + file_max; - + pfs= file_array + scan.first(); + PFS_file *pfs_last= file_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) @@ -901,17 +962,15 @@ void destroy_file(PFS_thread *thread, PF */ PFS_table* create_table(PFS_table_share *share, const void *identity) { - int pass; - uint i= randomized_index(identity, table_max); + PFS_scan scan; + uint random= randomized_index(identity, table_max); - /* - Pass 1: [random, table_max - 1] - Pass 2: [0, table_max - 1] - */ - for (pass= 1; pass <= 2; i=0, pass++) + for (scan.init(random, table_max); + scan.has_pass(); + scan.next_pass()) { - PFS_table *pfs= table_array + i; - PFS_table *pfs_last= table_array + table_max; + PFS_table *pfs= table_array + scan.first(); + PFS_table *pfs_last= table_array + scan.last(); for ( ; pfs < pfs_last; pfs++) { if (pfs->m_lock.is_free()) === modified file 'storage/perfschema/pfs_instr.h' --- a/storage/perfschema/pfs_instr.h 2010-03-31 14:05:33 +0000 +++ b/storage/perfschema/pfs_instr.h 2010-07-16 01:03:08 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2009 Sun Microsystems, Inc +/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -10,8 +10,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ #ifndef PFS_INSTR_H #define PFS_INSTR_H @@ -21,7 +21,6 @@ Performance schema instruments (declarations). */ -#include #include "pfs_lock.h" #include "pfs_instr_class.h" #include "pfs_events_waits.h" @@ -136,6 +135,48 @@ struct PFS_table : public PFS_instr */ #define LOCKER_STACK_SIZE 3 +/** + @def PFS_MAX_ALLOC_RETRY + Maximum number of times the code attempts to allocate an item + from internal buffers, before giving up. +*/ +#define PFS_MAX_ALLOC_RETRY 1000 + +#define PFS_MAX_SCAN_PASS 2 + +/** + Helper to scan circular buffers. + Given a buffer of size [0, max_size - 1], + and a random starting point in the buffer, + this helper returns up to two [first, last -1] intervals that: + - fit into the [0, max_size - 1] range, + - have a maximum combined length of at most PFS_MAX_ALLOC_RETRY. +*/ +struct PFS_scan +{ +public: + void init(uint random, uint max_size); + + bool has_pass() const + { return (m_pass < m_pass_max); } + + void next_pass() + { m_pass++; } + + uint first() const + { return m_first[m_pass]; } + + uint last() const + { return m_last[m_pass]; } + +private: + uint m_pass; + uint m_pass_max; + uint m_first[PFS_MAX_SCAN_PASS]; + uint m_last[PFS_MAX_SCAN_PASS]; +}; + + /** Instrumented thread implementation. @see PSI_thread. */ struct PFS_thread { --===============3005058440467022475== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///home/malff/BZR_TREE/mysql-trunk-bugfixing-\ # cleanup/ # testament_sha1: 4ffac7d24d43221521e5db8dc526d65c2ad38031 # timestamp: 2010-07-15 19:03:11 -0600 # base_revision_id: marc.alff@stripped\ # xq2skix202jenslo # # Begin bundle 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 --===============3005058440467022475==--