Commit a1d90f12 authored by Marc Alff's avatar Marc Alff

Bug#55462 Performance schema: reduce the overhead of PFS_events_waits::m_wait_class

This is a performance improvement fix.

Removed the "volatile" property of PFS_events_waits::m_wait_class.
Simplified the code accordingly.
parent 69091c49
...@@ -1117,7 +1117,6 @@ get_thread_mutex_locker_v1(PSI_mutex_locker_state *state, ...@@ -1117,7 +1117,6 @@ get_thread_mutex_locker_v1(PSI_mutex_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_mutex= pfs_mutex; pfs_locker->m_target.m_mutex= pfs_mutex;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1163,7 +1162,6 @@ get_thread_rwlock_locker_v1(PSI_rwlock_locker_state *state, ...@@ -1163,7 +1162,6 @@ get_thread_rwlock_locker_v1(PSI_rwlock_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_rwlock= pfs_rwlock; pfs_locker->m_target.m_rwlock= pfs_rwlock;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1222,7 +1220,6 @@ get_thread_cond_locker_v1(PSI_cond_locker_state *state, ...@@ -1222,7 +1220,6 @@ get_thread_cond_locker_v1(PSI_cond_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_cond= pfs_cond; pfs_locker->m_target.m_cond= pfs_cond;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1267,7 +1264,6 @@ get_thread_table_locker_v1(PSI_table_locker_state *state, ...@@ -1267,7 +1264,6 @@ get_thread_table_locker_v1(PSI_table_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_table= pfs_table; pfs_locker->m_target.m_table= pfs_table;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1320,7 +1316,6 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state, ...@@ -1320,7 +1316,6 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state,
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_file= pfs_file; pfs_locker->m_target.m_file= pfs_file;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1372,7 +1367,6 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state, ...@@ -1372,7 +1367,6 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_file= pfs_file; pfs_locker->m_target.m_file= pfs_file;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
...@@ -1441,7 +1435,6 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, ...@@ -1441,7 +1435,6 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
} }
PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
[pfs_thread->m_wait_locker_count]; [pfs_thread->m_wait_locker_count];
pfs_locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
pfs_locker->m_target.m_file= pfs_file; pfs_locker->m_target.m_file= pfs_file;
pfs_locker->m_waits_current.m_thread= pfs_thread; pfs_locker->m_waits_current.m_thread= pfs_thread;
......
...@@ -80,25 +80,10 @@ void cleanup_events_waits_history_long(void) ...@@ -80,25 +80,10 @@ void cleanup_events_waits_history_long(void)
events_waits_history_long_array= NULL; events_waits_history_long_array= NULL;
} }
static void copy_events_waits(PFS_events_waits *dest, static inline void copy_events_waits(PFS_events_waits *dest,
const PFS_events_waits *source) const PFS_events_waits *source)
{ {
/* m_wait_class must be the first member of PFS_events_waits. */ memcpy(dest, source, sizeof(PFS_events_waits));
compile_time_assert(offsetof(PFS_events_waits, m_wait_class) == 0);
char* dest_body= (reinterpret_cast<char*> (dest)) + sizeof(events_waits_class);
const char* source_body= (reinterpret_cast<const char*> (source))
+ sizeof(events_waits_class);
/* See comments in table_events_waits_common::make_row(). */
/* Signal readers they are about to read garbage ... */
dest->m_wait_class= NO_WAIT_CLASS;
/* ... that this can generate. */
memcpy(dest_body, source_body,
sizeof(PFS_events_waits) - sizeof(events_waits_class));
/* Signal readers the record is now clean again. */
dest->m_wait_class= source->m_wait_class;
} }
/** /**
...@@ -116,9 +101,7 @@ void insert_events_waits_history(PFS_thread *thread, PFS_events_waits *wait) ...@@ -116,9 +101,7 @@ void insert_events_waits_history(PFS_thread *thread, PFS_events_waits *wait)
causing a potential race condition. causing a potential race condition.
We are not testing for this and insert a possibly empty record, We are not testing for this and insert a possibly empty record,
to make this thread (the writer) faster. to make this thread (the writer) faster.
This is ok, the truncated data will have This is ok, the readers of m_waits_history will filter this out.
wait->m_wait_class == NO_WAIT_CLASS,
which readers of m_waits_history will filter out.
*/ */
copy_events_waits(&thread->m_waits_history[index], wait); copy_events_waits(&thread->m_waits_history[index], wait);
......
...@@ -97,7 +97,7 @@ struct PFS_events_waits ...@@ -97,7 +97,7 @@ struct PFS_events_waits
- TRUNCATE EVENTS_WAITS_HISTORY - TRUNCATE EVENTS_WAITS_HISTORY
- TRUNCATE EVENTS_WAITS_HISTORY_LONG - TRUNCATE EVENTS_WAITS_HISTORY_LONG
*/ */
volatile events_waits_class m_wait_class; events_waits_class m_wait_class;
/** Executing thread. */ /** Executing thread. */
PFS_thread *m_thread; PFS_thread *m_thread;
/** Instrument metadata. */ /** Instrument metadata. */
......
...@@ -217,16 +217,8 @@ void table_events_waits_common::make_row(bool thread_own_wait, ...@@ -217,16 +217,8 @@ void table_events_waits_common::make_row(bool thread_own_wait,
or 8 atomics per recorded event. or 8 atomics per recorded event.
The problem is that we record a *lot* of events ... The problem is that we record a *lot* of events ...
Instead, a *dirty* marking is done using m_wait_class. This code is prepared to accept *dirty* records,
Using m_wait_class alone does not guarantee anything, it just filters and sanitizes all the data before returning a row.
out most of the bad data.
This is acceptable because this code is garbage-proof,
and won't crash on bad data, only display it,
very rarely (which is accepted).
If a bad record is displayed, it's a very transient failure:
the next select * from EVENTS_WAITS_CURRENT/_HISTORY/_HISTORY_LONG will
show clean data again.
*/ */
m_row.m_thread_internal_id= safe_thread->m_thread_internal_id; m_row.m_thread_internal_id= safe_thread->m_thread_internal_id;
......
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