Skip to content

Commit 4d46b75

Browse files
committed
Bug#17766582 PERFORMANCE SCHEMA OVERHEAD IN PFS_LOCK This fix is a general cleanup for code involving atomic operations in the performance schema, to reduce overhead and improve code clarity. Changes implemented: 1) Removed 'volatile' in the code. The C 'volatile' keyword has nothing to do with atomic operations, and is confusing. This is a code cleanup. 2) Added missing PFS_cacheline_uint32 to atomic counters, to enforce no false sharing happens. This is a performance improvement. 3) Modified optimistic locks, for clarity. Pattern before: pfs_lock lock; m_lock.begin_optimistic_lock(&lock); m_lock.end_optimistic_lock(&lock); Pattern after: pfs_optimistic_state lock; m_lock.begin_optimistic_lock(&lock); m_lock.end_optimistic_lock(&lock); The new type, pfs_optimistic_state, better reflects that a state information is used in a begin / end section. This provides better typing, for type safety. Adjusted all the code accordingly. 4) Modified pfs_lock allocation, for performances. Pattern before: m_lock.is_free(); m_lock.free_to_dirty(); m_lock.dirty_to_allocated(); total: 0+1+2 = 3 atomic operations Note that free_to_dirty() could fail even for free locks, because the CAS can use an old version number, making the code attempt again another record. Pattern after: pfs_dirty_state dirty_state; m_lock.free_to_dirty(& dirty_state); m_lock.dirty_to_allocated(& dirty_state); total: 2+1 = 3 atomic operations. Now the code is garanteed to detect free records, because free_to_dirty() does an atomic load then a CAS. Adjusted all the code accordingly. 5) Modified pfs_lock deallocation, for performances. Pattern before: m_lock.allocated_to_free(); Total 2 atomic operations. Pattern after: m_lock.allocated_to_free(); Total 1 atomic operation. 6) Modified record updates, for performances. Pattern before: m_lock.allocated_to_dirty(); m_lock.dirty_to_allocated(); Total 4 atomic operations. Pattern after: pfs_dirty_state dirty_state; m_lock.allocated_to_dirty(& dirty_state); m_lock.dirty_to_allocated(& dirty_state); Total 2 atomic operations. Adjusted all the code accordingly. 7) Modified record peek, for reliability. Pattern before: m_lock.is_populated() used a dirty read, causing spurious missing records Pattern after: m_lock.is_populated() uses an atomic load, for correctness. This change is expected to resolve spurious test failures, where some records in performance schema tables are sometime missing, os some statistics (when computed on the fly) are sometime under evaluated.
1 parent 335e9b8 commit 4d46b75

File tree

57 files changed

+651
-615
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+651
-615
lines changed

storage/perfschema/pfs.cc

+17-12
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,7 @@ pfs_get_thread_v1(void)
21692169
*/
21702170
void pfs_set_thread_user_v1(const char *user, int user_len)
21712171
{
2172+
pfs_dirty_state dirty_state;
21722173
PFS_thread *pfs= my_pthread_get_THR_PFS();
21732174

21742175
DBUG_ASSERT((user != NULL) || (user_len == 0));
@@ -2180,7 +2181,7 @@ void pfs_set_thread_user_v1(const char *user, int user_len)
21802181

21812182
aggregate_thread(pfs, pfs->m_account, pfs->m_user, pfs->m_host);
21822183

2183-
pfs->m_session_lock.allocated_to_dirty();
2184+
pfs->m_session_lock.allocated_to_dirty(& dirty_state);
21842185

21852186
clear_thread_account(pfs);
21862187

@@ -2213,7 +2214,7 @@ void pfs_set_thread_user_v1(const char *user, int user_len)
22132214

22142215
pfs->set_enabled(enabled);
22152216

2216-
pfs->m_session_lock.dirty_to_allocated();
2217+
pfs->m_session_lock.dirty_to_allocated(& dirty_state);
22172218
}
22182219

22192220
/**
@@ -2223,6 +2224,7 @@ void pfs_set_thread_user_v1(const char *user, int user_len)
22232224
void pfs_set_thread_account_v1(const char *user, int user_len,
22242225
const char *host, int host_len)
22252226
{
2227+
pfs_dirty_state dirty_state;
22262228
PFS_thread *pfs= my_pthread_get_THR_PFS();
22272229

22282230
DBUG_ASSERT((user != NULL) || (user_len == 0));
@@ -2235,7 +2237,7 @@ void pfs_set_thread_account_v1(const char *user, int user_len,
22352237
if (unlikely(pfs == NULL))
22362238
return;
22372239

2238-
pfs->m_session_lock.allocated_to_dirty();
2240+
pfs->m_session_lock.allocated_to_dirty(& dirty_state);
22392241

22402242
clear_thread_account(pfs);
22412243

@@ -2271,7 +2273,7 @@ void pfs_set_thread_account_v1(const char *user, int user_len,
22712273
}
22722274
pfs->set_enabled(enabled);
22732275

2274-
pfs->m_session_lock.dirty_to_allocated();
2276+
pfs->m_session_lock.dirty_to_allocated(& dirty_state);
22752277
}
22762278

22772279
/**
@@ -2288,11 +2290,12 @@ void pfs_set_thread_db_v1(const char* db, int db_len)
22882290

22892291
if (likely(pfs != NULL))
22902292
{
2291-
pfs->m_stmt_lock.allocated_to_dirty();
2293+
pfs_dirty_state dirty_state;
2294+
pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
22922295
if (db_len > 0)
22932296
memcpy(pfs->m_dbname, db, db_len);
22942297
pfs->m_dbname_length= db_len;
2295-
pfs->m_stmt_lock.dirty_to_allocated();
2298+
pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
22962299
}
22972300
}
22982301

@@ -2342,6 +2345,7 @@ void pfs_set_thread_state_v1(const char* state)
23422345
*/
23432346
void pfs_set_thread_info_v1(const char* info, uint info_len)
23442347
{
2348+
pfs_dirty_state dirty_state;
23452349
PFS_thread *pfs= my_pthread_get_THR_PFS();
23462350

23472351
DBUG_ASSERT((info != NULL) || (info_len == 0));
@@ -2353,16 +2357,16 @@ void pfs_set_thread_info_v1(const char* info, uint info_len)
23532357
if (info_len > sizeof(pfs->m_processlist_info))
23542358
info_len= sizeof(pfs->m_processlist_info);
23552359

2356-
pfs->m_stmt_lock.allocated_to_dirty();
2360+
pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
23572361
memcpy(pfs->m_processlist_info, info, info_len);
23582362
pfs->m_processlist_info_length= info_len;
2359-
pfs->m_stmt_lock.dirty_to_allocated();
2363+
pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
23602364
}
23612365
else
23622366
{
2363-
pfs->m_stmt_lock.allocated_to_dirty();
2367+
pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
23642368
pfs->m_processlist_info_length= 0;
2365-
pfs->m_stmt_lock.dirty_to_allocated();
2369+
pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
23662370
}
23672371
}
23682372
}
@@ -5889,16 +5893,17 @@ int pfs_set_thread_connect_attrs_v1(const char *buffer, uint length,
58895893

58905894
if (likely(thd != NULL) && session_connect_attrs_size_per_thread > 0)
58915895
{
5896+
pfs_dirty_state dirty_state;
58925897
const CHARSET_INFO *cs = static_cast<const CHARSET_INFO *> (from_cs);
58935898

58945899
/* copy from the input buffer as much as we can fit */
58955900
uint copy_size= (uint)(length < session_connect_attrs_size_per_thread ?
58965901
length : session_connect_attrs_size_per_thread);
5897-
thd->m_session_lock.allocated_to_dirty();
5902+
thd->m_session_lock.allocated_to_dirty(& dirty_state);
58985903
memcpy(thd->m_session_connect_attrs, buffer, copy_size);
58995904
thd->m_session_connect_attrs_length= copy_size;
59005905
thd->m_session_connect_attrs_cs_number= cs->number;
5901-
thd->m_session_lock.dirty_to_allocated();
5906+
thd->m_session_lock.dirty_to_allocated(& dirty_state);
59025907

59035908
if (copy_size == length)
59045909
return 0;

storage/perfschema/pfs_account.cc

+55-57
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ find_or_create_account(PFS_thread *thread,
260260
const uint retry_max= 3;
261261
uint index;
262262
uint attempts= 0;
263+
pfs_dirty_state dirty_state;
263264

264265
search:
265266
entry= reinterpret_cast<PFS_account**>
@@ -286,72 +287,69 @@ find_or_create_account(PFS_thread *thread,
286287
index= PFS_atomic::add_u32(& monotonic.m_u32, 1) % account_max;
287288
pfs= account_array + index;
288289

289-
if (pfs->m_lock.is_free())
290+
if (pfs->m_lock.free_to_dirty(& dirty_state))
290291
{
291-
if (pfs->m_lock.free_to_dirty())
292+
pfs->m_key= key;
293+
if (username_length > 0)
294+
pfs->m_username= &pfs->m_key.m_hash_key[0];
295+
else
296+
pfs->m_username= NULL;
297+
pfs->m_username_length= username_length;
298+
299+
if (hostname_length > 0)
300+
pfs->m_hostname= &pfs->m_key.m_hash_key[username_length + 1];
301+
else
302+
pfs->m_hostname= NULL;
303+
pfs->m_hostname_length= hostname_length;
304+
305+
pfs->m_user= find_or_create_user(thread, username, username_length);
306+
pfs->m_host= find_or_create_host(thread, hostname, hostname_length);
307+
308+
pfs->init_refcount();
309+
pfs->reset_stats();
310+
pfs->m_disconnected_count= 0;
311+
312+
if (username_length > 0 && hostname_length > 0)
292313
{
293-
pfs->m_key= key;
294-
if (username_length > 0)
295-
pfs->m_username= &pfs->m_key.m_hash_key[0];
296-
else
297-
pfs->m_username= NULL;
298-
pfs->m_username_length= username_length;
299-
300-
if (hostname_length > 0)
301-
pfs->m_hostname= &pfs->m_key.m_hash_key[username_length + 1];
302-
else
303-
pfs->m_hostname= NULL;
304-
pfs->m_hostname_length= hostname_length;
305-
306-
pfs->m_user= find_or_create_user(thread, username, username_length);
307-
pfs->m_host= find_or_create_host(thread, hostname, hostname_length);
308-
309-
pfs->init_refcount();
310-
pfs->reset_stats();
311-
pfs->m_disconnected_count= 0;
312-
313-
if (username_length > 0 && hostname_length > 0)
314-
{
315-
lookup_setup_actor(thread, username, username_length, hostname, hostname_length,
316-
& pfs->m_enabled);
317-
}
318-
else
319-
pfs->m_enabled= true;
314+
lookup_setup_actor(thread, username, username_length, hostname, hostname_length,
315+
& pfs->m_enabled);
316+
}
317+
else
318+
pfs->m_enabled= true;
320319

321-
int res;
322-
pfs->m_lock.dirty_to_allocated();
323-
res= lf_hash_insert(&account_hash, pins, &pfs);
324-
if (likely(res == 0))
325-
{
326-
return pfs;
327-
}
320+
int res;
321+
pfs->m_lock.dirty_to_allocated(& dirty_state);
322+
res= lf_hash_insert(&account_hash, pins, &pfs);
323+
if (likely(res == 0))
324+
{
325+
return pfs;
326+
}
328327

329-
if (pfs->m_user)
330-
{
331-
pfs->m_user->release();
332-
pfs->m_user= NULL;
333-
}
334-
if (pfs->m_host)
335-
{
336-
pfs->m_host->release();
337-
pfs->m_host= NULL;
338-
}
328+
if (pfs->m_user)
329+
{
330+
pfs->m_user->release();
331+
pfs->m_user= NULL;
332+
}
333+
if (pfs->m_host)
334+
{
335+
pfs->m_host->release();
336+
pfs->m_host= NULL;
337+
}
339338

340-
pfs->m_lock.allocated_to_free();
339+
pfs->m_lock.allocated_to_free();
341340

342-
if (res > 0)
341+
if (res > 0)
342+
{
343+
if (++retry_count > retry_max)
343344
{
344-
if (++retry_count > retry_max)
345-
{
346-
account_lost++;
347-
return NULL;
348-
}
349-
goto search;
345+
account_lost++;
346+
return NULL;
350347
}
351-
352-
account_lost++;
353-
return NULL;
348+
goto search;
354349
}
350+
351+
account_lost++;
352+
return NULL;
355353
}
356354
}
357355

0 commit comments

Comments
 (0)