1 /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software Foundation, 21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ 22 23 #ifndef PFS_STAT_H 24 #define PFS_STAT_H 25 26 #include "sql_const.h" 27 /* memcpy */ 28 #include "string.h" 29 30 /** 31 @file storage/perfschema/pfs_stat.h 32 Statistics (declarations). 33 */ 34 35 /** 36 @addtogroup Performance_schema_buffers 37 @{ 38 */ 39 40 /** Single statistic. */ 41 struct PFS_single_stat 42 { 43 /** Count of values. */ 44 ulonglong m_count; 45 /** Sum of values. */ 46 ulonglong m_sum; 47 /** Minimum value. */ 48 ulonglong m_min; 49 /** Maximum value. */ 50 ulonglong m_max; 51 PFS_single_statPFS_single_stat52 PFS_single_stat() 53 { 54 m_count= 0; 55 m_sum= 0; 56 m_min= ULONGLONG_MAX; 57 m_max= 0; 58 } 59 resetPFS_single_stat60 inline void reset(void) 61 { 62 m_count= 0; 63 m_sum= 0; 64 m_min= ULONGLONG_MAX; 65 m_max= 0; 66 } 67 has_timed_statsPFS_single_stat68 inline bool has_timed_stats() const 69 { 70 return (m_min <= m_max); 71 } 72 aggregatePFS_single_stat73 inline void aggregate(const PFS_single_stat *stat) 74 { 75 m_count+= stat->m_count; 76 m_sum+= stat->m_sum; 77 if (unlikely(m_min > stat->m_min)) 78 m_min= stat->m_min; 79 if (unlikely(m_max < stat->m_max)) 80 m_max= stat->m_max; 81 } 82 aggregate_countedPFS_single_stat83 inline void aggregate_counted() 84 { 85 m_count++; 86 } 87 aggregate_countedPFS_single_stat88 inline void aggregate_counted(ulonglong count) 89 { 90 m_count+= count; 91 } 92 aggregate_valuePFS_single_stat93 inline void aggregate_value(ulonglong value) 94 { 95 m_count++; 96 m_sum+= value; 97 if (unlikely(m_min > value)) 98 m_min= value; 99 if (unlikely(m_max < value)) 100 m_max= value; 101 } 102 }; 103 104 /** Combined statistic. */ 105 struct PFS_byte_stat : public PFS_single_stat 106 { 107 /** Byte count statistics */ 108 ulonglong m_bytes; 109 110 /* Aggregate wait stats, event count and byte count */ aggregatePFS_byte_stat111 inline void aggregate(const PFS_byte_stat *stat) 112 { 113 PFS_single_stat::aggregate(stat); 114 m_bytes+= stat->m_bytes; 115 } 116 117 /* Aggregate individual wait time, event count and byte count */ aggregatePFS_byte_stat118 inline void aggregate(ulonglong wait, ulonglong bytes) 119 { 120 aggregate_value(wait); 121 m_bytes+= bytes; 122 } 123 124 /* Aggregate wait stats and event count */ aggregate_waitsPFS_byte_stat125 inline void aggregate_waits(const PFS_byte_stat *stat) 126 { 127 PFS_single_stat::aggregate(stat); 128 } 129 130 /* Aggregate event count and byte count */ aggregate_countedPFS_byte_stat131 inline void aggregate_counted() 132 { 133 PFS_single_stat::aggregate_counted(); 134 } 135 136 /* Aggregate event count and byte count */ aggregate_countedPFS_byte_stat137 inline void aggregate_counted(ulonglong bytes) 138 { 139 PFS_single_stat::aggregate_counted(); 140 m_bytes+= bytes; 141 } 142 PFS_byte_statPFS_byte_stat143 PFS_byte_stat() 144 { 145 reset(); 146 } 147 resetPFS_byte_stat148 inline void reset(void) 149 { 150 PFS_single_stat::reset(); 151 m_bytes= 0; 152 } 153 }; 154 155 /** Statistics for mutex usage. */ 156 struct PFS_mutex_stat 157 { 158 /** Wait statistics. */ 159 PFS_single_stat m_wait_stat; 160 /** 161 Lock statistics. 162 This statistic is not exposed in user visible tables yet. 163 */ 164 PFS_single_stat m_lock_stat; 165 aggregatePFS_mutex_stat166 inline void aggregate(const PFS_mutex_stat *stat) 167 { 168 m_wait_stat.aggregate(&stat->m_wait_stat); 169 m_lock_stat.aggregate(&stat->m_lock_stat); 170 } 171 resetPFS_mutex_stat172 inline void reset(void) 173 { 174 m_wait_stat.reset(); 175 m_lock_stat.reset(); 176 } 177 }; 178 179 /** Statistics for rwlock usage. */ 180 struct PFS_rwlock_stat 181 { 182 /** Wait statistics. */ 183 PFS_single_stat m_wait_stat; 184 /** 185 RWLock read lock usage statistics. 186 This statistic is not exposed in user visible tables yet. 187 */ 188 PFS_single_stat m_read_lock_stat; 189 /** 190 RWLock write lock usage statistics. 191 This statistic is not exposed in user visible tables yet. 192 */ 193 PFS_single_stat m_write_lock_stat; 194 aggregatePFS_rwlock_stat195 inline void aggregate(const PFS_rwlock_stat *stat) 196 { 197 m_wait_stat.aggregate(&stat->m_wait_stat); 198 m_read_lock_stat.aggregate(&stat->m_read_lock_stat); 199 m_write_lock_stat.aggregate(&stat->m_write_lock_stat); 200 } 201 resetPFS_rwlock_stat202 inline void reset(void) 203 { 204 m_wait_stat.reset(); 205 m_read_lock_stat.reset(); 206 m_write_lock_stat.reset(); 207 } 208 }; 209 210 /** Statistics for COND usage. */ 211 struct PFS_cond_stat 212 { 213 /** Wait statistics. */ 214 PFS_single_stat m_wait_stat; 215 /** 216 Number of times a condition was signalled. 217 This statistic is not exposed in user visible tables yet. 218 */ 219 ulonglong m_signal_count; 220 /** 221 Number of times a condition was broadcast. 222 This statistic is not exposed in user visible tables yet. 223 */ 224 ulonglong m_broadcast_count; 225 aggregatePFS_cond_stat226 inline void aggregate(const PFS_cond_stat *stat) 227 { 228 m_wait_stat.aggregate(&stat->m_wait_stat); 229 m_signal_count+= stat->m_signal_count; 230 m_broadcast_count+= stat->m_broadcast_count; 231 } 232 resetPFS_cond_stat233 inline void reset(void) 234 { 235 m_wait_stat.reset(); 236 m_signal_count= 0; 237 m_broadcast_count= 0; 238 } 239 }; 240 241 /** Statistics for FILE IO. Used for both waits and byte counts. */ 242 struct PFS_file_io_stat 243 { 244 /** READ statistics */ 245 PFS_byte_stat m_read; 246 /** WRITE statistics */ 247 PFS_byte_stat m_write; 248 /** Miscelleanous statistics */ 249 PFS_byte_stat m_misc; 250 resetPFS_file_io_stat251 inline void reset(void) 252 { 253 m_read.reset(); 254 m_write.reset(); 255 m_misc.reset(); 256 } 257 aggregatePFS_file_io_stat258 inline void aggregate(const PFS_file_io_stat *stat) 259 { 260 m_read.aggregate(&stat->m_read); 261 m_write.aggregate(&stat->m_write); 262 m_misc.aggregate(&stat->m_misc); 263 } 264 265 /* Sum waits and byte counts */ sumPFS_file_io_stat266 inline void sum(PFS_byte_stat *stat) 267 { 268 stat->aggregate(&m_read); 269 stat->aggregate(&m_write); 270 stat->aggregate(&m_misc); 271 } 272 273 /* Sum waits only */ sum_waitsPFS_file_io_stat274 inline void sum_waits(PFS_single_stat *stat) 275 { 276 stat->aggregate(&m_read); 277 stat->aggregate(&m_write); 278 stat->aggregate(&m_misc); 279 } 280 }; 281 282 /** Statistics for FILE usage. */ 283 struct PFS_file_stat 284 { 285 /** Number of current open handles. */ 286 ulong m_open_count; 287 /** File IO statistics. */ 288 PFS_file_io_stat m_io_stat; 289 aggregatePFS_file_stat290 inline void aggregate(const PFS_file_stat *stat) 291 { 292 m_io_stat.aggregate(&stat->m_io_stat); 293 } 294 295 /** Reset file statistics. */ resetPFS_file_stat296 inline void reset(void) 297 { 298 m_io_stat.reset(); 299 } 300 }; 301 302 /** Statistics for stage usage. */ 303 struct PFS_stage_stat 304 { 305 PFS_single_stat m_timer1_stat; 306 resetPFS_stage_stat307 inline void reset(void) 308 { m_timer1_stat.reset(); } 309 aggregate_countedPFS_stage_stat310 inline void aggregate_counted() 311 { m_timer1_stat.aggregate_counted(); } 312 aggregate_valuePFS_stage_stat313 inline void aggregate_value(ulonglong value) 314 { m_timer1_stat.aggregate_value(value); } 315 aggregatePFS_stage_stat316 inline void aggregate(PFS_stage_stat *stat) 317 { m_timer1_stat.aggregate(& stat->m_timer1_stat); } 318 }; 319 320 /** Statistics for statement usage. */ 321 struct PFS_statement_stat 322 { 323 PFS_single_stat m_timer1_stat; 324 ulonglong m_error_count; 325 ulonglong m_warning_count; 326 ulonglong m_rows_affected; 327 ulonglong m_lock_time; 328 ulonglong m_rows_sent; 329 ulonglong m_rows_examined; 330 ulonglong m_created_tmp_disk_tables; 331 ulonglong m_created_tmp_tables; 332 ulonglong m_select_full_join; 333 ulonglong m_select_full_range_join; 334 ulonglong m_select_range; 335 ulonglong m_select_range_check; 336 ulonglong m_select_scan; 337 ulonglong m_sort_merge_passes; 338 ulonglong m_sort_range; 339 ulonglong m_sort_rows; 340 ulonglong m_sort_scan; 341 ulonglong m_no_index_used; 342 ulonglong m_no_good_index_used; 343 PFS_statement_statPFS_statement_stat344 PFS_statement_stat() 345 { 346 m_error_count= 0; 347 m_warning_count= 0; 348 m_rows_affected= 0; 349 m_lock_time= 0; 350 m_rows_sent= 0; 351 m_rows_examined= 0; 352 m_created_tmp_disk_tables= 0; 353 m_created_tmp_tables= 0; 354 m_select_full_join= 0; 355 m_select_full_range_join= 0; 356 m_select_range= 0; 357 m_select_range_check= 0; 358 m_select_scan= 0; 359 m_sort_merge_passes= 0; 360 m_sort_range= 0; 361 m_sort_rows= 0; 362 m_sort_scan= 0; 363 m_no_index_used= 0; 364 m_no_good_index_used= 0; 365 } 366 resetPFS_statement_stat367 inline void reset(void) 368 { 369 m_timer1_stat.reset(); 370 m_error_count= 0; 371 m_warning_count= 0; 372 m_rows_affected= 0; 373 m_lock_time= 0; 374 m_rows_sent= 0; 375 m_rows_examined= 0; 376 m_created_tmp_disk_tables= 0; 377 m_created_tmp_tables= 0; 378 m_select_full_join= 0; 379 m_select_full_range_join= 0; 380 m_select_range= 0; 381 m_select_range_check= 0; 382 m_select_scan= 0; 383 m_sort_merge_passes= 0; 384 m_sort_range= 0; 385 m_sort_rows= 0; 386 m_sort_scan= 0; 387 m_no_index_used= 0; 388 m_no_good_index_used= 0; 389 } 390 aggregate_countedPFS_statement_stat391 inline void aggregate_counted() 392 { m_timer1_stat.aggregate_counted(); } 393 aggregate_valuePFS_statement_stat394 inline void aggregate_value(ulonglong value) 395 { m_timer1_stat.aggregate_value(value); } 396 aggregatePFS_statement_stat397 inline void aggregate(PFS_statement_stat *stat) 398 { 399 m_timer1_stat.aggregate(& stat->m_timer1_stat); 400 401 m_error_count+= stat->m_error_count; 402 m_warning_count+= stat->m_warning_count; 403 m_rows_affected+= stat->m_rows_affected; 404 m_lock_time+= stat->m_lock_time; 405 m_rows_sent+= stat->m_rows_sent; 406 m_rows_examined+= stat->m_rows_examined; 407 m_created_tmp_disk_tables+= stat->m_created_tmp_disk_tables; 408 m_created_tmp_tables+= stat->m_created_tmp_tables; 409 m_select_full_join+= stat->m_select_full_join; 410 m_select_full_range_join+= stat->m_select_full_range_join; 411 m_select_range+= stat->m_select_range; 412 m_select_range_check+= stat->m_select_range_check; 413 m_select_scan+= stat->m_select_scan; 414 m_sort_merge_passes+= stat->m_sort_merge_passes; 415 m_sort_range+= stat->m_sort_range; 416 m_sort_rows+= stat->m_sort_rows; 417 m_sort_scan+= stat->m_sort_scan; 418 m_no_index_used+= stat->m_no_index_used; 419 m_no_good_index_used+= stat->m_no_good_index_used; 420 } 421 }; 422 423 /** Single table io statistic. */ 424 struct PFS_table_io_stat 425 { 426 bool m_has_data; 427 /** FETCH statistics */ 428 PFS_single_stat m_fetch; 429 /** INSERT statistics */ 430 PFS_single_stat m_insert; 431 /** UPDATE statistics */ 432 PFS_single_stat m_update; 433 /** DELETE statistics */ 434 PFS_single_stat m_delete; 435 PFS_table_io_statPFS_table_io_stat436 PFS_table_io_stat() 437 { 438 m_has_data= false; 439 } 440 resetPFS_table_io_stat441 inline void reset(void) 442 { 443 m_has_data= false; 444 m_fetch.reset(); 445 m_insert.reset(); 446 m_update.reset(); 447 m_delete.reset(); 448 } 449 aggregatePFS_table_io_stat450 inline void aggregate(const PFS_table_io_stat *stat) 451 { 452 if (stat->m_has_data) 453 { 454 m_has_data= true; 455 m_fetch.aggregate(&stat->m_fetch); 456 m_insert.aggregate(&stat->m_insert); 457 m_update.aggregate(&stat->m_update); 458 m_delete.aggregate(&stat->m_delete); 459 } 460 } 461 sumPFS_table_io_stat462 inline void sum(PFS_single_stat *result) 463 { 464 if (m_has_data) 465 { 466 result->aggregate(& m_fetch); 467 result->aggregate(& m_insert); 468 result->aggregate(& m_update); 469 result->aggregate(& m_delete); 470 } 471 } 472 }; 473 474 enum PFS_TL_LOCK_TYPE 475 { 476 /* Locks from enum thr_lock */ 477 PFS_TL_READ= 0, 478 PFS_TL_READ_WITH_SHARED_LOCKS= 1, 479 PFS_TL_READ_HIGH_PRIORITY= 2, 480 PFS_TL_READ_NO_INSERT= 3, 481 PFS_TL_WRITE_ALLOW_WRITE= 4, 482 PFS_TL_WRITE_CONCURRENT_INSERT= 5, 483 PFS_TL_WRITE_DELAYED= 6, 484 PFS_TL_WRITE_LOW_PRIORITY= 7, 485 PFS_TL_WRITE= 8, 486 487 /* Locks for handler::ha_external_lock() */ 488 PFS_TL_READ_EXTERNAL= 9, 489 PFS_TL_WRITE_EXTERNAL= 10 490 }; 491 492 #define COUNT_PFS_TL_LOCK_TYPE 11 493 494 /** Statistics for table locks. */ 495 struct PFS_table_lock_stat 496 { 497 PFS_single_stat m_stat[COUNT_PFS_TL_LOCK_TYPE]; 498 resetPFS_table_lock_stat499 inline void reset(void) 500 { 501 PFS_single_stat *pfs= & m_stat[0]; 502 PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; 503 for ( ; pfs < pfs_last ; pfs++) 504 pfs->reset(); 505 } 506 aggregatePFS_table_lock_stat507 inline void aggregate(const PFS_table_lock_stat *stat) 508 { 509 PFS_single_stat *pfs= & m_stat[0]; 510 PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; 511 const PFS_single_stat *pfs_from= & stat->m_stat[0]; 512 for ( ; pfs < pfs_last ; pfs++, pfs_from++) 513 pfs->aggregate(pfs_from); 514 } 515 sumPFS_table_lock_stat516 inline void sum(PFS_single_stat *result) 517 { 518 PFS_single_stat *pfs= & m_stat[0]; 519 PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; 520 for ( ; pfs < pfs_last ; pfs++) 521 result->aggregate(pfs); 522 } 523 }; 524 525 /** Statistics for TABLE usage. */ 526 struct PFS_table_stat 527 { 528 /** 529 Statistics, per index. 530 Each index stat is in [0, MAX_INDEXES-1], 531 stats when using no index are in [MAX_INDEXES]. 532 */ 533 PFS_table_io_stat m_index_stat[MAX_INDEXES + 1]; 534 535 /** 536 Statistics, per lock type. 537 */ 538 PFS_table_lock_stat m_lock_stat; 539 540 /** Reset table io statistic. */ reset_ioPFS_table_stat541 inline void reset_io(void) 542 { 543 PFS_table_io_stat *stat= & m_index_stat[0]; 544 PFS_table_io_stat *stat_last= & m_index_stat[MAX_INDEXES + 1]; 545 for ( ; stat < stat_last ; stat++) 546 stat->reset(); 547 } 548 549 /** Reset table lock statistic. */ reset_lockPFS_table_stat550 inline void reset_lock(void) 551 { 552 m_lock_stat.reset(); 553 } 554 555 /** Reset table statistic. */ resetPFS_table_stat556 inline void reset(void) 557 { 558 reset_io(); 559 reset_lock(); 560 } 561 fast_reset_ioPFS_table_stat562 inline void fast_reset_io(void) 563 { 564 memcpy(& m_index_stat, & g_reset_template.m_index_stat, sizeof(m_index_stat)); 565 } 566 fast_reset_lockPFS_table_stat567 inline void fast_reset_lock(void) 568 { 569 memcpy(& m_lock_stat, & g_reset_template.m_lock_stat, sizeof(m_lock_stat)); 570 } 571 fast_resetPFS_table_stat572 inline void fast_reset(void) 573 { 574 memcpy(this, & g_reset_template, sizeof(*this)); 575 } 576 aggregate_ioPFS_table_stat577 inline void aggregate_io(const PFS_table_stat *stat, uint key_count) 578 { 579 PFS_table_io_stat *to_stat; 580 PFS_table_io_stat *to_stat_last; 581 const PFS_table_io_stat *from_stat; 582 583 DBUG_ASSERT(key_count <= MAX_INDEXES); 584 585 /* Aggregate stats for each index, if any */ 586 to_stat= & m_index_stat[0]; 587 to_stat_last= to_stat + key_count; 588 from_stat= & stat->m_index_stat[0]; 589 for ( ; to_stat < to_stat_last ; from_stat++, to_stat++) 590 to_stat->aggregate(from_stat); 591 592 /* Aggregate stats for the table */ 593 to_stat= & m_index_stat[MAX_INDEXES]; 594 from_stat= & stat->m_index_stat[MAX_INDEXES]; 595 to_stat->aggregate(from_stat); 596 } 597 aggregate_lockPFS_table_stat598 inline void aggregate_lock(const PFS_table_stat *stat) 599 { 600 m_lock_stat.aggregate(& stat->m_lock_stat); 601 } 602 aggregatePFS_table_stat603 inline void aggregate(const PFS_table_stat *stat, uint key_count) 604 { 605 aggregate_io(stat, key_count); 606 aggregate_lock(stat); 607 } 608 sum_ioPFS_table_stat609 inline void sum_io(PFS_single_stat *result, uint key_count) 610 { 611 PFS_table_io_stat *stat; 612 PFS_table_io_stat *stat_last; 613 614 DBUG_ASSERT(key_count <= MAX_INDEXES); 615 616 /* Sum stats for each index, if any */ 617 stat= & m_index_stat[0]; 618 stat_last= stat + key_count; 619 for ( ; stat < stat_last ; stat++) 620 stat->sum(result); 621 622 /* Sum stats for the table */ 623 m_index_stat[MAX_INDEXES].sum(result); 624 } 625 sum_lockPFS_table_stat626 inline void sum_lock(PFS_single_stat *result) 627 { 628 m_lock_stat.sum(result); 629 } 630 sumPFS_table_stat631 inline void sum(PFS_single_stat *result, uint key_count) 632 { 633 sum_io(result, key_count); 634 sum_lock(result); 635 } 636 637 static struct PFS_table_stat g_reset_template; 638 }; 639 640 /** Statistics for SOCKET IO. Used for both waits and byte counts. */ 641 struct PFS_socket_io_stat 642 { 643 /** READ statistics */ 644 PFS_byte_stat m_read; 645 /** WRITE statistics */ 646 PFS_byte_stat m_write; 647 /** Miscelleanous statistics */ 648 PFS_byte_stat m_misc; 649 resetPFS_socket_io_stat650 inline void reset(void) 651 { 652 m_read.reset(); 653 m_write.reset(); 654 m_misc.reset(); 655 } 656 aggregatePFS_socket_io_stat657 inline void aggregate(const PFS_socket_io_stat *stat) 658 { 659 m_read.aggregate(&stat->m_read); 660 m_write.aggregate(&stat->m_write); 661 m_misc.aggregate(&stat->m_misc); 662 } 663 664 /* Sum waits and byte counts */ sumPFS_socket_io_stat665 inline void sum(PFS_byte_stat *stat) 666 { 667 stat->aggregate(&m_read); 668 stat->aggregate(&m_write); 669 stat->aggregate(&m_misc); 670 } 671 672 /* Sum waits only */ sum_waitsPFS_socket_io_stat673 inline void sum_waits(PFS_single_stat *stat) 674 { 675 stat->aggregate(&m_read); 676 stat->aggregate(&m_write); 677 stat->aggregate(&m_misc); 678 } 679 }; 680 681 /** Statistics for SOCKET usage. */ 682 struct PFS_socket_stat 683 { 684 /** Socket timing and byte count statistics per operation */ 685 PFS_socket_io_stat m_io_stat; 686 687 /** Reset socket statistics. */ resetPFS_socket_stat688 inline void reset(void) 689 { 690 m_io_stat.reset(); 691 } 692 }; 693 694 struct PFS_connection_stat 695 { PFS_connection_statPFS_connection_stat696 PFS_connection_stat() 697 : m_current_connections(0), 698 m_total_connections(0) 699 {} 700 701 ulonglong m_current_connections; 702 ulonglong m_total_connections; 703 aggregate_activePFS_connection_stat704 inline void aggregate_active(ulonglong active) 705 { 706 m_current_connections+= active; 707 m_total_connections+= active; 708 } 709 aggregate_disconnectedPFS_connection_stat710 inline void aggregate_disconnected(ulonglong disconnected) 711 { 712 m_total_connections+= disconnected; 713 } 714 }; 715 716 /** @} */ 717 #endif 718 719