From: Marc Alff Date: March 31 2010 3:48pm Subject: bzr commit into mysql-next-mr-bugfixing branch (marc.alff:3144) Bug#52502 List-Archive: http://lists.mysql.com/commits/104734 X-Bug: 52502 Message-Id: <20100331154852.6EB0032F50C@MarcBook.local> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_Rl5C5VCxqhl5XYumN5gARQ)" --Boundary_(ID_Rl5C5VCxqhl5XYumN5gARQ) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///Users/malff/BZR_TREE/mysql-next-mr-bugfixing-52502/ based on revid:alik@stripped 3144 Marc Alff 2010-03-31 Bug#52502 Performance schema does not start with large mutex_instance buffers This is a performance issue affecting scalability. Prior to this fix, the performance schema code did not scale well when a very large number of instruments are created in the code. The root cause was create_mutex() spinning "forever", trying to find an empty slot in a full mutex_array. With this fix: - functions like create_mutex() abort sooner, when used with a very large array which is full or almost full. - randomize_index() has been revised to improve the statistical spread of values in the mutex_array. See the comments in the code for details. Other allocation functions similar to create_mutex() have been also fixed. No MTR test case provided (performance scalability issue). Fix tested manually. 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-01-12 01:47:27 +0000 +++ b/storage/perfschema/pfs_global.h 2010-03-31 15:48:47 +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 @@ -30,27 +30,49 @@ 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; + value%= max_size; + + result= static_cast (value); + seed2= seed1*seed1; + seed1= result; + + return result; } void pfs_print_error(const char *format, ...); === modified file 'storage/perfschema/pfs_instr.cc' --- a/storage/perfschema/pfs_instr.cc 2010-03-22 12:48:18 +0000 +++ b/storage/perfschema/pfs_instr.cc 2010-03-31 15:48:47 +0000 @@ -454,6 +454,7 @@ void cleanup_file_hash(void) PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity) { int pass; + uint attempt= 0; uint i= randomized_index(identity, mutex_max); /* @@ -464,7 +465,9 @@ PFS_mutex* create_mutex(PFS_mutex_class { PFS_mutex *pfs= mutex_array + i; PFS_mutex *pfs_last= mutex_array + mutex_max; - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { @@ -512,6 +515,7 @@ void destroy_mutex(PFS_mutex *pfs) PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity) { int pass; + uint attempt= 0; uint i= randomized_index(identity, rwlock_max); /* @@ -522,7 +526,9 @@ PFS_rwlock* create_rwlock(PFS_rwlock_cla { PFS_rwlock *pfs= rwlock_array + i; PFS_rwlock *pfs_last= rwlock_array + rwlock_max; - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { @@ -576,6 +582,7 @@ void destroy_rwlock(PFS_rwlock *pfs) PFS_cond* create_cond(PFS_cond_class *klass, const void *identity) { int pass; + uint attempt= 0; uint i= randomized_index(identity, cond_max); /* @@ -586,7 +593,9 @@ PFS_cond* create_cond(PFS_cond_class *kl { PFS_cond *pfs= cond_array + i; PFS_cond *pfs_last= cond_array + cond_max; - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { @@ -634,6 +643,7 @@ PFS_thread* create_thread(PFS_thread_cla ulong thread_id) { int pass; + uint attempt= 0; uint i= randomized_index(identity, thread_max); /* @@ -644,7 +654,9 @@ PFS_thread* create_thread(PFS_thread_cla { PFS_thread *pfs= thread_array + i; PFS_thread *pfs_last= thread_array + thread_max; - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { @@ -728,6 +740,7 @@ find_or_create_file(PFS_thread *thread, { PFS_file *pfs; int pass; + uint attempt= 0; if (! filename_hash_inited) { @@ -849,8 +862,9 @@ search: { pfs= file_array + i; PFS_file *pfs_last= file_array + file_max; - - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { @@ -935,6 +949,7 @@ void destroy_file(PFS_thread *thread, PF PFS_table* create_table(PFS_table_share *share, const void *identity) { int pass; + uint attempt= 0; uint i= randomized_index(identity, table_max); /* @@ -945,7 +960,9 @@ PFS_table* create_table(PFS_table_share { PFS_table *pfs= table_array + i; PFS_table *pfs_last= table_array + table_max; - for ( ; pfs < pfs_last; pfs++) + for ( ; + (pfs < pfs_last) && (attempt < PFS_MAX_ALLOC_RETRY); + pfs++, attempt++) { if (pfs->m_lock.is_free()) { === modified file 'storage/perfschema/pfs_instr.h' --- a/storage/perfschema/pfs_instr.h 2010-01-12 01:47:27 +0000 +++ b/storage/perfschema/pfs_instr.h 2010-03-31 15:48:47 +0000 @@ -136,6 +136,13 @@ struct PFS_table : public PFS_instr */ #define LOCKER_STACK_SIZE 3 +/** + @def PFS_MAX_ALLOC_RETRY + Maximun number of times the code attempts to allocate an item + from internal buffers, before giving up. +*/ +#define PFS_MAX_ALLOC_RETRY 1000 + /** Instrumented thread implementation. @see PSI_thread. */ struct PFS_thread { --Boundary_(ID_Rl5C5VCxqhl5XYumN5gARQ) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name="bzr/marc.alff@stripped" Content-transfer-encoding: 7BIT Content-disposition: inline; filename="bzr/marc.alff@stripped" # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-next-mr-bugfixing-\ # 52502/ # testament_sha1: 2b941d26b6777dbf0f373b4906f497cad9f567cf # timestamp: 2010-03-31 09:48:51 -0600 # base_revision_id: alik@stripped # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWYGq4T4ABU9fgFIQW3///3sH 3Ou////wYAt9Xvveh6bijoACi9gH32+77gBRL1qLs1F8NCJpNqYo8mp5RsU9J6ajJ6myjQAaAAAD Uwp6AQ1MU00T1B6jQ0fqgAAANAAMiamyo9U03qgNDIAAAAAAAADCQEINCp7FMp71J6p+pGT1AMgD IAAAlKIDQNBoAAGgGjQABoAACSIJoATQmQ0ASeTU8inqbSeRP0jU9TYU9CSJzQIAXcN+4D9128X4 ZCu6TaCSSk3+nkHfjl3ityHK8hPkTcagf7qSIzN4Ap+aT0WkiCs3owSARt3IbDZwfE70JI5LkOvY orMgAWyVKO6XOgwdQGubxz6qL0YBBBeCqgIKIADlsjCOeBGRPNKLymLKq9KO56x2NhI19wfI4xhm GZJfTAC4DlzmXnlLn4cOjPt6Y2DVl4BlnneAMIzrtxUYkL0gg2FEsSYuCGOiJxiYpzwcWtpo8YW3 iBSgqQU+IsuSiy3HwMx2UaQVLm/gDTFTteao6ZCqrswgGVl2BN5DsvkP5LpoveoHkBnukxc/xK0g 5g5sXkhTWTNzQgQbWxvK9iBGOgtCEjuV9WoTlhmjEFOMnrceRuaKgkb8ajpRfTkpOVKGTGPyl/Lo y2ohQmakhlyvzk+zYxunoM0a0URLiN9TJ41ki2IVIQqXNK7yULKW1y7L1lY430B7XC19gyk+HTlt rqtKSjIvIXzGJYxMbTmUjZEvs+vWjlDdx38UbqA7yv+f92By552MIH7kIylo/DkzSYnCI0iqqtAs 3O7AfWyueU9oiMGPmpmCVwzgYGa9utnu5K9F12domQoWOkqA0bLQCCm7ygNjJLf7LO4UgO5kucOA 4FxBmc/MTB2i9Pq9XAXr3Nt75Qg5d6q+fV7BN3fllg+2UbmFmKYqxOLAmbIy7ce/w2cJ7bC4Vlkn jM4b5eN510zPajWw2CVPxVRAY0AAQYo8j9VZAZwQPDfhWQzRTTGo54E0ZYXUCUPsWbevrN/DHaJW q68Zkwi6DDHTxlYTvqXs0bamV57NkWRWCxZLwY8mCdU/mRgeLRkwhUf7HS4hSSHdIkWERJ2H5Iwu WCBgnaBdUfheUNpjjdWgaHki049Rwt5xOhMJEA/JA9agA0uSNhIrh5rRur21DSUiT6whakTEWqyQ 906cI18uRZiVEcK2LQc7CZ3oMjIY6+MiI6lxCPQKn1vxhbC/NMMgWaRqd22tVLI3mwRxoJKlykM6 3nubmIxFjiVkiwOw124Cya2dQ40jKUcREeUuMJ4CW4fG8IyI1OUhedNpQRzkZWUbOSJoLXUoJgsS 3D0VlcEEE9gh4HNfXkIrNRtDgcDAmUPvdhgWXUjuJxNW+BcWv5755xL20EbRlis1G0xN5DQbnIvo OThSjNxYVW7SaCsojl0mQwIE8ryKMC8P0zPBBbG1iwzfCDPKAjiJJnYvHMCnjHWaiMCQ+ZVXZv1I 1D75GReabc8dVzZbcY1NnVYXElKfARM1FKhpCOKECQwX8RFay9rby0qJl6CWNsYElaaxjXrxwrK6 i8yI2kDUMMObl1dGcWKDU4s6xwvRKYSFPdxyGYH0F4Cja8h9l0iYLvVjBBg/Vh4ljitTx9lJS9FK +6pqAmPR3xHwGCISSQ7/mHTmxE4FLXzjhOp+kS9if/wH8AOTNjMMMN8rPoBKX7gen6gQ9oH0AncA 2Le2dJgRgyBv1qAYD6ARPMzyA/iLNRmYsd4XgYgQONfXt93OfNB9gPsB6jn/PoPQwdCJyBYKBRk/ vnrQoUfw2hb3CASEG4qBsUDENDI2XRQzjoyn6QKkOENL4EEfo7QeCiwxoIjkxVbbZpl8BKo8P0I8 17yGh/UD+wLAtgpsccOMMIpMjfPzmTno3+9vpkJRA4hEU55MzBS2yy2lEvVAsqGOUhUGlgQY8RXI UAoPRYZGDJef4HcaDnme8yMz7rkMjFHoGWSa0ZHE/NA/avk3RXrQjXAu3PolAYiJWnDqND0FNg3Y scIMzdBAcqbadioWo65VqDa7UY2YyYSapFiAYREoSVcAgupowHqfjlCSlJ5QguRh7kDrA2yglobC RUiaJD2COQwNpea5MDfz8ZwaTUTcoM7AwcdDqEbu3f3CsT08zVv+mCmWsSQDsuKGS2kGTSN96WWo ndeGakgmpNQSm9xmRVwSKxfVeFXDfBivvg5zn3aig1FlJrhvF2xtjrWFxjpe6sCchSV5YZQZaDI6 D4mvkuKtNlJliOlgvmkBDbD2mEW4AQQUwstvU4tikqiljMEZEBWt2qLkRmhDbmZCROAPY9q4IyVZ rHWQvK9D1oasLBAETOnTZst5A9N2dBRKYOC25vQWZBoJpBGyJtjpeDXujn9BI9J1nV2HOTMyoSgS MwiVlxYdNEHY4wlgHug+4f0iIfwvBXhW1rLk39G/3ikT7ZhAOhITp12ssKIMm7lcqlDMBpVrMV1n kngm+3cu0/LrDBd443rIMDncA10v644YiIoPNmTJmXFEepF440OsgggoA82Glxeq7xJ4nMIrigbB IPWifYI+HC/seSNLbVHhyeHjzCOUzuuHkilgWE9G7GDxwSPI66rlS7ewrWVPWLKBDdjTDVndr92v GF97CbtEN2su/lbKGNyZAxrueItaZmMopDnCWc49COthD70ce2jDUr+G8MRVMVMg5lzBbxCxnwYG +buqHIIZHSuoiWWBYLlLoqTgnXiwftESfndFL5CBoriqZhsBcDWoWvfWV7WPvqSEADV1lq5Me3gM hDI5gw/nv+R5IZOSUlgssQ/DXHhKvtdQwCtYsWXBPEET8px4066vlFVVs46ejsQfBs5RBpEkMgjQ PbUKRU6TIKnB6s2xvikSHlqaNnpYPn3VHXE1QQAyQOIRTSaKCSKARAdjBdef5fGwfBC65ScoPBHQ h7/PqJ1jxj2vBitpIACEEszRhHTi5FYYVjsj46hQrcfoanmCcUcx3A5soLK51sEMDRNeOmOBQbiP j35xFYgZcODh77MBCkPCXM7ACAvuKFzDMM0hYL8RHXSzdsqfSklskW6DZQYQf65wc2JHVrw2HeNJ k8EUrJja0ohAI3TJRX6yCDlvRmgoIIszMxVqbQ3tHoCfo77NddQiyIoVuzfH0s8kYoALFZ48aX9m JOVp26O9gPMhTEgIXd4EIXCDQQfLh3Dt1AsTSIuGQvLF5WdZYSlEx9ruDLCM8Jek4SiYVSS88giI NDqWWQ1OKHxRPW0YNAgrahEBQPggiXohl2v2WOGb62M9C8eDVSRAdsQqCizhJ1BpMFnXDEEbBDrn 0vAuTSAm0mk1JjjD1y0nQGlQawhf1dSBwPlVBUF4i1kbAwKSRAyUYTZjNt9hIDQVhLcLAoHCoTgd LIOvKIiCuoFkiKziWOWQtjU8wU1BKAdhLBSaHTEQit84wkMURiSBnPANzqy8a6RlYMwus+LVIOvM 6groHa1qthBEim5Q4lGv3aBVeZ2CfSJuZFKtG1mLZJpd1Rs/auTTBVwv6aHT0uj1rlcvZL+0DF1w m/dB7xDwWCfxWcIdAiQHESWx1TtYQcm0kmo9egInIyE407tKcsu2ktYI5Rjs0sQ/i7kinChIQNVw nwA= --Boundary_(ID_Rl5C5VCxqhl5XYumN5gARQ)--