Skip to content

Commit 79f3324

Browse files
committed
Bug#13862186 - PERFORMANCE SCHEMA OVERHEAD FOR TABLE AGGREGATES
Before this fix, the performance schema would use a lot of CPU to execute PFS_table aggregate functions in general. With this fix, execution has been improved, per the following changes: 1) In PFS_table::aggregate(), the code used to call safe_aggregate() if any stat was present. When both m_has_io_stats and m_has_lock_stats are true, this is correct. When only m_has_io_stats or m_has_lock_stats is true, this is overkill. Calling safe_aggregate_io() or safe_aggregate_lock() is better in this case. 2) Likewise for PFS_table::sanitized_aggregate() 3) In PFS_table_stat::aggregate_io() and PFS_table_stat::sum_io(), the code did loop on every possible index in the [0, MAX_INDEXES-1] range, regardless on whether the table actually had that many index used. Now the code only use index statistics for index that do exist, using the [0, key_count] range. Calling code has been adjusted accordingly. 4) For a given index statistic, PFS_table_io_stat::m_has_data was added. This boolean indicates of data has been collected for this index. Using this flag saves a lot, because even if a table can effectively have many indexes, a thread opening the table, performing a select, and closing the table is more likely to use one index only (or a few), instead of all the indexes available. When aggregating the statistics for this thread to the table statistics, testing this flag saves on CPU. 5) For code clarity only (no performance change), MAX_KEY has been replaced by MAX_INDEXES, which is more accurate. These two constants are synonym.
1 parent 57acdd1 commit 79f3324

11 files changed

+157
-63
lines changed

storage/perfschema/pfs.cc

+9-5
Original file line numberDiff line numberDiff line change
@@ -3682,23 +3682,27 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
36823682
DBUG_ASSERT(table != NULL);
36833683

36843684
PFS_single_stat *stat;
3685+
PFS_table_io_stat *table_io_stat;
36853686

36863687
DBUG_ASSERT((state->m_index < table->m_share->m_key_count) ||
3687-
(state->m_index == MAX_KEY));
3688+
(state->m_index == MAX_INDEXES));
3689+
3690+
table_io_stat= & table->m_table_stat.m_index_stat[state->m_index];
3691+
table_io_stat->m_has_data= true;
36883692

36893693
switch (state->m_io_operation)
36903694
{
36913695
case PSI_TABLE_FETCH_ROW:
3692-
stat= & table->m_table_stat.m_index_stat[state->m_index].m_fetch;
3696+
stat= & table_io_stat->m_fetch;
36933697
break;
36943698
case PSI_TABLE_WRITE_ROW:
3695-
stat= & table->m_table_stat.m_index_stat[state->m_index].m_insert;
3699+
stat= & table_io_stat->m_insert;
36963700
break;
36973701
case PSI_TABLE_UPDATE_ROW:
3698-
stat= & table->m_table_stat.m_index_stat[state->m_index].m_update;
3702+
stat= & table_io_stat->m_update;
36993703
break;
37003704
case PSI_TABLE_DELETE_ROW:
3701-
stat= & table->m_table_stat.m_index_stat[state->m_index].m_delete;
3705+
stat= & table_io_stat->m_delete;
37023706
break;
37033707
default:
37043708
DBUG_ASSERT(false);

storage/perfschema/pfs_instr.cc

+25-9
Original file line numberDiff line numberDiff line change
@@ -1329,12 +1329,24 @@ void PFS_table::sanitized_aggregate(void)
13291329
*/
13301330
PFS_table_share *safe_share= sanitize_table_share(m_share);
13311331
PFS_thread *safe_thread= sanitize_thread(m_thread_owner);
1332-
if ((safe_share != NULL && safe_thread != NULL) &&
1333-
(m_has_io_stats || m_has_lock_stats))
1332+
if ((safe_share != NULL && safe_thread != NULL))
13341333
{
1335-
safe_aggregate(& m_table_stat, safe_share, safe_thread);
1336-
m_has_io_stats= false;
1337-
m_has_lock_stats= false;
1334+
if (m_has_io_stats && m_has_lock_stats)
1335+
{
1336+
safe_aggregate(& m_table_stat, safe_share, safe_thread);
1337+
m_has_io_stats= false;
1338+
m_has_lock_stats= false;
1339+
}
1340+
else if (m_has_io_stats)
1341+
{
1342+
safe_aggregate_io(& m_table_stat, safe_share, safe_thread);
1343+
m_has_io_stats= false;
1344+
}
1345+
else if (m_has_lock_stats)
1346+
{
1347+
safe_aggregate_lock(& m_table_stat, safe_share, safe_thread);
1348+
m_has_lock_stats= false;
1349+
}
13381350
}
13391351
}
13401352

@@ -1368,6 +1380,8 @@ void PFS_table::safe_aggregate(PFS_table_stat *table_stat,
13681380
DBUG_ASSERT(table_share != NULL);
13691381
DBUG_ASSERT(thread != NULL);
13701382

1383+
uint key_count= sanitize_index_count(table_share->m_key_count);
1384+
13711385
if (flag_thread_instrumentation && thread->m_enabled)
13721386
{
13731387
PFS_single_stat *event_name_array;
@@ -1379,7 +1393,7 @@ void PFS_table::safe_aggregate(PFS_table_stat *table_stat,
13791393
(for wait/io/table/sql/handler)
13801394
*/
13811395
index= global_table_io_class.m_event_name_index;
1382-
table_stat->sum_io(& event_name_array[index]);
1396+
table_stat->sum_io(& event_name_array[index], key_count);
13831397

13841398
/*
13851399
Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
@@ -1390,7 +1404,7 @@ void PFS_table::safe_aggregate(PFS_table_stat *table_stat,
13901404
}
13911405

13921406
/* Aggregate to TABLE_IO_SUMMARY, TABLE_LOCK_SUMMARY */
1393-
table_share->m_table_stat.aggregate(table_stat);
1407+
table_share->m_table_stat.aggregate(table_stat, key_count);
13941408
table_stat->fast_reset();
13951409
}
13961410

@@ -1402,6 +1416,8 @@ void PFS_table::safe_aggregate_io(PFS_table_stat *table_stat,
14021416
DBUG_ASSERT(table_share != NULL);
14031417
DBUG_ASSERT(thread != NULL);
14041418

1419+
uint key_count= sanitize_index_count(table_share->m_key_count);
1420+
14051421
if (flag_thread_instrumentation && thread->m_enabled)
14061422
{
14071423
PFS_single_stat *event_name_array;
@@ -1413,11 +1429,11 @@ void PFS_table::safe_aggregate_io(PFS_table_stat *table_stat,
14131429
(for wait/io/table/sql/handler)
14141430
*/
14151431
index= global_table_io_class.m_event_name_index;
1416-
table_stat->sum_io(& event_name_array[index]);
1432+
table_stat->sum_io(& event_name_array[index], key_count);
14171433
}
14181434

14191435
/* Aggregate to TABLE_IO_SUMMARY */
1420-
table_share->m_table_stat.aggregate_io(table_stat);
1436+
table_share->m_table_stat.aggregate_io(table_stat, key_count);
14211437
table_stat->fast_reset_io();
14221438
}
14231439

storage/perfschema/pfs_instr.h

+17-4
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,24 @@ struct PFS_table
196196
*/
197197
void aggregate(void)
198198
{
199-
if (likely((m_thread_owner != NULL) && (m_has_io_stats || m_has_lock_stats)))
199+
if (likely(m_thread_owner != NULL))
200200
{
201-
safe_aggregate(& m_table_stat, m_share, m_thread_owner);
202-
m_has_io_stats= false;
203-
m_has_lock_stats= false;
201+
if (m_has_io_stats && m_has_lock_stats)
202+
{
203+
safe_aggregate(& m_table_stat, m_share, m_thread_owner);
204+
m_has_io_stats= false;
205+
m_has_lock_stats= false;
206+
}
207+
else if (m_has_io_stats)
208+
{
209+
safe_aggregate_io(& m_table_stat, m_share, m_thread_owner);
210+
m_has_io_stats= false;
211+
}
212+
else if (m_has_lock_stats)
213+
{
214+
safe_aggregate_lock(& m_table_stat, m_share, m_thread_owner);
215+
m_has_lock_stats= false;
216+
}
204217
}
205218
}
206219

storage/perfschema/pfs_instr_class.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
11931193
pfs_key->m_name_length= len;
11941194
}
11951195

1196-
pfs_key_last= pfs->m_keys + MAX_KEY;
1196+
pfs_key_last= pfs->m_keys + MAX_INDEXES;
11971197
for ( ; pfs_key < pfs_key_last; pfs_key++)
11981198
pfs_key->m_name_length= 0;
11991199
}
@@ -1353,9 +1353,10 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread,
13531353

13541354
void PFS_table_share::aggregate_io(void)
13551355
{
1356+
uint safe_key_count= sanitize_index_count(m_key_count);
13561357
uint index= global_table_io_class.m_event_name_index;
13571358
PFS_single_stat *table_io_total= & global_instr_class_waits_array[index];
1358-
m_table_stat.sum_io(table_io_total);
1359+
m_table_stat.sum_io(table_io_total, safe_key_count);
13591360
m_table_stat.fast_reset_io();
13601361
}
13611362

storage/perfschema/pfs_instr_class.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,20 @@ struct PFS_table_share
316316
/** Table statistics. */
317317
PFS_table_stat m_table_stat;
318318
/** Index names. */
319-
PFS_table_key m_keys[MAX_KEY];
319+
PFS_table_key m_keys[MAX_INDEXES];
320320

321321
private:
322322
/** Number of opened table handles. */
323323
int m_refcount;
324324
};
325325

326+
inline uint sanitize_index_count(uint count)
327+
{
328+
if (likely(count <= MAX_INDEXES))
329+
return count;
330+
return 0;
331+
}
332+
326333
/**
327334
Instrument controlling all table io.
328335
This instrument is used with table SETUP_OBJECTS.

storage/perfschema/pfs_stat.h

+58-23
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct PFS_statement_stat
329329
/** Single table io statistic. */
330330
struct PFS_table_io_stat
331331
{
332+
bool m_has_data;
332333
/** FETCH statistics */
333334
PFS_single_stat m_fetch;
334335
/** INSERT statistics */
@@ -338,8 +339,14 @@ struct PFS_table_io_stat
338339
/** DELETE statistics */
339340
PFS_single_stat m_delete;
340341

342+
PFS_table_io_stat()
343+
{
344+
m_has_data= false;
345+
}
346+
341347
inline void reset(void)
342348
{
349+
m_has_data= false;
343350
m_fetch.reset();
344351
m_insert.reset();
345352
m_update.reset();
@@ -348,18 +355,25 @@ struct PFS_table_io_stat
348355

349356
inline void aggregate(const PFS_table_io_stat *stat)
350357
{
351-
m_fetch.aggregate(&stat->m_fetch);
352-
m_insert.aggregate(&stat->m_insert);
353-
m_update.aggregate(&stat->m_update);
354-
m_delete.aggregate(&stat->m_delete);
358+
if (stat->m_has_data)
359+
{
360+
m_has_data= true;
361+
m_fetch.aggregate(&stat->m_fetch);
362+
m_insert.aggregate(&stat->m_insert);
363+
m_update.aggregate(&stat->m_update);
364+
m_delete.aggregate(&stat->m_delete);
365+
}
355366
}
356367

357368
inline void sum(PFS_single_stat *result)
358369
{
359-
result->aggregate(& m_fetch);
360-
result->aggregate(& m_insert);
361-
result->aggregate(& m_update);
362-
result->aggregate(& m_delete);
370+
if (m_has_data)
371+
{
372+
result->aggregate(& m_fetch);
373+
result->aggregate(& m_insert);
374+
result->aggregate(& m_update);
375+
result->aggregate(& m_delete);
376+
}
363377
}
364378
};
365379

@@ -419,10 +433,10 @@ struct PFS_table_stat
419433
{
420434
/**
421435
Statistics, per index.
422-
Each index stat is in [0, MAX_KEY-1],
423-
stats when using no index are in [MAX_KEY].
436+
Each index stat is in [0, MAX_INDEXES-1],
437+
stats when using no index are in [MAX_INDEXES].
424438
*/
425-
PFS_table_io_stat m_index_stat[MAX_KEY + 1];
439+
PFS_table_io_stat m_index_stat[MAX_INDEXES + 1];
426440

427441
/**
428442
Statistics, per lock type.
@@ -433,7 +447,7 @@ struct PFS_table_stat
433447
inline void reset_io(void)
434448
{
435449
PFS_table_io_stat *stat= & m_index_stat[0];
436-
PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1];
450+
PFS_table_io_stat *stat_last= & m_index_stat[MAX_INDEXES + 1];
437451
for ( ; stat < stat_last ; stat++)
438452
stat->reset();
439453
}
@@ -466,42 +480,63 @@ struct PFS_table_stat
466480
memcpy(this, & g_reset_template, sizeof(*this));
467481
}
468482

469-
inline void aggregate_io(const PFS_table_stat *stat)
483+
inline void aggregate_io(const PFS_table_stat *stat, uint key_count)
470484
{
471-
PFS_table_io_stat *to_stat= & m_index_stat[0];
472-
PFS_table_io_stat *to_stat_last= & m_index_stat[MAX_KEY + 1];
473-
const PFS_table_io_stat *from_stat= & stat->m_index_stat[0];
485+
PFS_table_io_stat *to_stat;
486+
PFS_table_io_stat *to_stat_last;
487+
const PFS_table_io_stat *from_stat;
488+
489+
DBUG_ASSERT(key_count <= MAX_INDEXES);
490+
491+
/* Aggregate stats for each index, if any */
492+
to_stat= & m_index_stat[0];
493+
to_stat_last= to_stat + key_count;
494+
from_stat= & stat->m_index_stat[0];
474495
for ( ; to_stat < to_stat_last ; from_stat++, to_stat++)
475496
to_stat->aggregate(from_stat);
497+
498+
/* Aggregate stats for the table */
499+
to_stat= & m_index_stat[MAX_INDEXES];
500+
from_stat= & stat->m_index_stat[MAX_INDEXES];
501+
to_stat->aggregate(from_stat);
476502
}
477503

478504
inline void aggregate_lock(const PFS_table_stat *stat)
479505
{
480506
m_lock_stat.aggregate(& stat->m_lock_stat);
481507
}
482508

483-
inline void aggregate(const PFS_table_stat *stat)
509+
inline void aggregate(const PFS_table_stat *stat, uint key_count)
484510
{
485-
aggregate_io(stat);
511+
aggregate_io(stat, key_count);
486512
aggregate_lock(stat);
487513
}
488514

489-
inline void sum_io(PFS_single_stat *result)
515+
inline void sum_io(PFS_single_stat *result, uint key_count)
490516
{
491-
PFS_table_io_stat *stat= & m_index_stat[0];
492-
PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1];
517+
PFS_table_io_stat *stat;
518+
PFS_table_io_stat *stat_last;
519+
520+
DBUG_ASSERT(key_count <= MAX_INDEXES);
521+
522+
/* Sum stats for each index, if any */
523+
stat= & m_index_stat[0];
524+
stat_last= stat + key_count;
493525
for ( ; stat < stat_last ; stat++)
494526
stat->sum(result);
527+
528+
/* Sum stats for the table */
529+
m_index_stat[MAX_INDEXES].sum(result);
495530
}
496531

497532
inline void sum_lock(PFS_single_stat *result)
498533
{
499534
m_lock_stat.sum(result);
500535
}
501536

502-
inline void sum(PFS_single_stat *result)
537+
inline void sum(PFS_single_stat *result, uint key_count)
503538
{
504-
sum_io(result);
539+
sum_io(result, key_count);
505540
sum_lock(result);
506541
}
507542

0 commit comments

Comments
 (0)