diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /storage/perfschema/pfs_stat.h | |
parent | Initial commit. (diff) | |
download | mariadb-3f619478f796eddbba6e39502fe941b285dd97b1.tar.xz mariadb-3f619478f796eddbba6e39502fe941b285dd97b1.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/perfschema/pfs_stat.h')
-rw-r--r-- | storage/perfschema/pfs_stat.h | 1332 |
1 files changed, 1332 insertions, 0 deletions
diff --git a/storage/perfschema/pfs_stat.h b/storage/perfschema/pfs_stat.h new file mode 100644 index 00000000..af0be085 --- /dev/null +++ b/storage/perfschema/pfs_stat.h @@ -0,0 +1,1332 @@ +/* Copyright (c) 2008, 2023, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef PFS_STAT_H +#define PFS_STAT_H + +#include <algorithm> +#include "sql_const.h" +/* memcpy */ +#include "string.h" + +/** + @file storage/perfschema/pfs_stat.h + Statistics (declarations). +*/ + +/** + @addtogroup Performance_schema_buffers + @{ +*/ + +/** Single statistic. */ +struct PFS_single_stat +{ + /** Count of values. */ + ulonglong m_count; + /** Sum of values. */ + ulonglong m_sum; + /** Minimum value. */ + ulonglong m_min; + /** Maximum value. */ + ulonglong m_max; + + PFS_single_stat() + { + m_count= 0; + m_sum= 0; + m_min= ULLONG_MAX; + m_max= 0; + } + + inline void reset(void) + { + m_count= 0; + m_sum= 0; + m_min= ULLONG_MAX; + m_max= 0; + } + + inline bool has_timed_stats() const + { + return (m_min <= m_max); + } + + inline void aggregate(const PFS_single_stat *stat) + { + if (stat->m_count != 0) + { + m_count+= stat->m_count; + m_sum+= stat->m_sum; + if (unlikely(m_min > stat->m_min)) + m_min= stat->m_min; + if (unlikely(m_max < stat->m_max)) + m_max= stat->m_max; + } + } + + inline void aggregate_no_check(const PFS_single_stat *stat) + { + m_count+= stat->m_count; + m_sum+= stat->m_sum; + if (unlikely(m_min > stat->m_min)) + m_min= stat->m_min; + if (unlikely(m_max < stat->m_max)) + m_max= stat->m_max; + } + + inline void aggregate_counted() + { + m_count++; + } + + inline void aggregate_counted(ulonglong count) + { + m_count+= count; + } + + inline void aggregate_value(ulonglong value) + { + m_count++; + m_sum+= value; + if (unlikely(m_min > value)) + m_min= value; + if (unlikely(m_max < value)) + m_max= value; + } + + inline void aggregate_many_value(ulonglong value, ulonglong count) + { + m_count+= count; + m_sum+= value; + if (unlikely(m_min > value)) + m_min= value; + if (unlikely(m_max < value)) + m_max= value; + } +}; + +/** Combined statistic. */ +struct PFS_byte_stat : public PFS_single_stat +{ + /** Byte count statistics */ + ulonglong m_bytes; + + /** Aggregate wait stats, event count and byte count */ + inline void aggregate(const PFS_byte_stat *stat) + { + if (stat->m_count != 0) + { + PFS_single_stat::aggregate_no_check(stat); + m_bytes+= stat->m_bytes; + } + } + + /** Aggregate wait stats, event count and byte count */ + inline void aggregate_no_check(const PFS_byte_stat *stat) + { + PFS_single_stat::aggregate_no_check(stat); + m_bytes+= stat->m_bytes; + } + + /** Aggregate individual wait time, event count and byte count */ + inline void aggregate(ulonglong wait, ulonglong bytes) + { + aggregate_value(wait); + m_bytes+= bytes; + } + + /** Aggregate wait stats and event count */ + inline void aggregate_waits(const PFS_byte_stat *stat) + { + PFS_single_stat::aggregate(stat); + } + + /** Aggregate event count and byte count */ + inline void aggregate_counted() + { + PFS_single_stat::aggregate_counted(); + } + + /** Aggregate event count and byte count */ + inline void aggregate_counted(ulonglong bytes) + { + PFS_single_stat::aggregate_counted(); + m_bytes+= bytes; + } + + PFS_byte_stat() + { + reset(); + } + + inline void reset(void) + { + PFS_single_stat::reset(); + m_bytes= 0; + } +}; + +/** Statistics for mutex usage. */ +struct PFS_mutex_stat +{ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; +#ifdef PFS_LATER + /** + Lock statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_lock_stat; +#endif + + inline void aggregate(const PFS_mutex_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); +#ifdef PFS_LATER + m_lock_stat.aggregate(&stat->m_lock_stat); +#endif + } + + inline void reset(void) + { + m_wait_stat.reset(); +#ifdef PFS_LATER + m_lock_stat.reset(); +#endif + } +}; + +/** Statistics for rwlock usage. */ +struct PFS_rwlock_stat +{ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; +#ifdef PFS_LATER + /** + RWLock read lock usage statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_read_lock_stat; + /** + RWLock write lock usage statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_write_lock_stat; +#endif + + inline void aggregate(const PFS_rwlock_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); +#ifdef PFS_LATER + m_read_lock_stat.aggregate(&stat->m_read_lock_stat); + m_write_lock_stat.aggregate(&stat->m_write_lock_stat); +#endif + } + + inline void reset(void) + { + m_wait_stat.reset(); +#ifdef PFS_LATER + m_read_lock_stat.reset(); + m_write_lock_stat.reset(); +#endif + } +}; + +/** Statistics for COND usage. */ +struct PFS_cond_stat +{ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; +#ifdef PFS_LATER + /** + Number of times a condition was signalled. + This statistic is not exposed in user visible tables yet. + */ + ulonglong m_signal_count; + /** + Number of times a condition was broadcast. + This statistic is not exposed in user visible tables yet. + */ + ulonglong m_broadcast_count; +#endif + + inline void aggregate(const PFS_cond_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); +#ifdef PFS_LATER + m_signal_count+= stat->m_signal_count; + m_broadcast_count+= stat->m_broadcast_count; +#endif + } + + inline void reset(void) + { + m_wait_stat.reset(); +#ifdef PFS_LATER + m_signal_count= 0; + m_broadcast_count= 0; +#endif + } +}; + +/** Statistics for FILE IO. Used for both waits and byte counts. */ +struct PFS_file_io_stat +{ + /** READ statistics */ + PFS_byte_stat m_read; + /** WRITE statistics */ + PFS_byte_stat m_write; + /** Miscellaneous statistics */ + PFS_byte_stat m_misc; + + inline void reset(void) + { + m_read.reset(); + m_write.reset(); + m_misc.reset(); + } + + inline void aggregate(const PFS_file_io_stat *stat) + { + m_read.aggregate(&stat->m_read); + m_write.aggregate(&stat->m_write); + m_misc.aggregate(&stat->m_misc); + } + + /* Sum waits and byte counts */ + inline void sum(PFS_byte_stat *stat) + { + stat->aggregate(&m_read); + stat->aggregate(&m_write); + stat->aggregate(&m_misc); + } + + /* Sum waits only */ + inline void sum_waits(PFS_single_stat *stat) + { + stat->aggregate(&m_read); + stat->aggregate(&m_write); + stat->aggregate(&m_misc); + } +}; + +/** Statistics for FILE usage. */ +struct PFS_file_stat +{ + /** Number of current open handles. */ + ulong m_open_count; + /** File IO statistics. */ + PFS_file_io_stat m_io_stat; + + inline void aggregate(const PFS_file_stat *stat) + { + m_io_stat.aggregate(&stat->m_io_stat); + } + + /** Reset file statistics. */ + inline void reset(void) + { + m_io_stat.reset(); + } +}; + +/** Statistics for stage usage. */ +struct PFS_stage_stat +{ + PFS_single_stat m_timer1_stat; + + inline void reset(void) + { m_timer1_stat.reset(); } + + inline void aggregate_counted() + { m_timer1_stat.aggregate_counted(); } + + inline void aggregate_value(ulonglong value) + { m_timer1_stat.aggregate_value(value); } + + inline void aggregate(const PFS_stage_stat *stat) + { m_timer1_stat.aggregate(& stat->m_timer1_stat); } +}; + +/** Statistics for stored program usage. */ +struct PFS_sp_stat +{ + PFS_single_stat m_timer1_stat; + + inline void reset(void) + { m_timer1_stat.reset(); } + + inline void aggregate_counted() + { m_timer1_stat.aggregate_counted(); } + + inline void aggregate_value(ulonglong value) + { m_timer1_stat.aggregate_value(value); } + + inline void aggregate(const PFS_stage_stat *stat) + { m_timer1_stat.aggregate(& stat->m_timer1_stat); } +}; + +/** Statistics for prepared statement usage. */ +struct PFS_prepared_stmt_stat +{ + PFS_single_stat m_timer1_stat; + + inline void reset(void) + { m_timer1_stat.reset(); } + + inline void aggregate_counted() + { m_timer1_stat.aggregate_counted(); } + + inline void aggregate_value(ulonglong value) + { m_timer1_stat.aggregate_value(value); } + + inline void aggregate(PFS_stage_stat *stat) + { m_timer1_stat.aggregate(& stat->m_timer1_stat); } +}; + +/** + Statistics for statement usage. + This structure uses lazy initialization, + controlled by member @c m_timer1_stat.m_count. +*/ +struct PFS_statement_stat +{ + PFS_single_stat m_timer1_stat; + ulonglong m_error_count; + ulonglong m_warning_count; + ulonglong m_rows_affected; + ulonglong m_lock_time; + ulonglong m_rows_sent; + ulonglong m_rows_examined; + ulonglong m_created_tmp_disk_tables; + ulonglong m_created_tmp_tables; + ulonglong m_select_full_join; + ulonglong m_select_full_range_join; + ulonglong m_select_range; + ulonglong m_select_range_check; + ulonglong m_select_scan; + ulonglong m_sort_merge_passes; + ulonglong m_sort_range; + ulonglong m_sort_rows; + ulonglong m_sort_scan; + ulonglong m_no_index_used; + ulonglong m_no_good_index_used; + + PFS_statement_stat() + { + reset(); + } + + inline void reset() + { + m_timer1_stat.m_count= 0; + } + + inline void mark_used() + { + delayed_reset(); + } + +private: + inline void delayed_reset(void) + { + if (m_timer1_stat.m_count == 0) + { + m_timer1_stat.reset(); + m_error_count= 0; + m_warning_count= 0; + m_rows_affected= 0; + m_lock_time= 0; + m_rows_sent= 0; + m_rows_examined= 0; + m_created_tmp_disk_tables= 0; + m_created_tmp_tables= 0; + m_select_full_join= 0; + m_select_full_range_join= 0; + m_select_range= 0; + m_select_range_check= 0; + m_select_scan= 0; + m_sort_merge_passes= 0; + m_sort_range= 0; + m_sort_rows= 0; + m_sort_scan= 0; + m_no_index_used= 0; + m_no_good_index_used= 0; + } + } + +public: + inline void aggregate_counted() + { + delayed_reset(); + m_timer1_stat.aggregate_counted(); + } + + inline void aggregate_value(ulonglong value) + { + delayed_reset(); + m_timer1_stat.aggregate_value(value); + } + + inline void aggregate(const PFS_statement_stat *stat) + { + if (stat->m_timer1_stat.m_count != 0) + { + delayed_reset(); + m_timer1_stat.aggregate_no_check(& stat->m_timer1_stat); + + m_error_count+= stat->m_error_count; + m_warning_count+= stat->m_warning_count; + m_rows_affected+= stat->m_rows_affected; + m_lock_time+= stat->m_lock_time; + m_rows_sent+= stat->m_rows_sent; + m_rows_examined+= stat->m_rows_examined; + m_created_tmp_disk_tables+= stat->m_created_tmp_disk_tables; + m_created_tmp_tables+= stat->m_created_tmp_tables; + m_select_full_join+= stat->m_select_full_join; + m_select_full_range_join+= stat->m_select_full_range_join; + m_select_range+= stat->m_select_range; + m_select_range_check+= stat->m_select_range_check; + m_select_scan+= stat->m_select_scan; + m_sort_merge_passes+= stat->m_sort_merge_passes; + m_sort_range+= stat->m_sort_range; + m_sort_rows+= stat->m_sort_rows; + m_sort_scan+= stat->m_sort_scan; + m_no_index_used+= stat->m_no_index_used; + m_no_good_index_used+= stat->m_no_good_index_used; + } + } +}; + +/** Statistics for transaction usage. */ +struct PFS_transaction_stat +{ + PFS_single_stat m_read_write_stat; + PFS_single_stat m_read_only_stat; + + ulonglong m_savepoint_count; + ulonglong m_rollback_to_savepoint_count; + ulonglong m_release_savepoint_count; + + PFS_transaction_stat() + { + m_savepoint_count= 0; + m_rollback_to_savepoint_count= 0; + m_release_savepoint_count= 0; + } + + ulonglong count(void) + { + return (m_read_write_stat.m_count + m_read_only_stat.m_count); + } + + inline void reset(void) + { + m_read_write_stat.reset(); + m_read_only_stat.reset(); + m_savepoint_count= 0; + m_rollback_to_savepoint_count= 0; + m_release_savepoint_count= 0; + } + + inline void aggregate(const PFS_transaction_stat *stat) + { + m_read_write_stat.aggregate(&stat->m_read_write_stat); + m_read_only_stat.aggregate(&stat->m_read_only_stat); + m_savepoint_count+= stat->m_savepoint_count; + m_rollback_to_savepoint_count+= stat->m_rollback_to_savepoint_count; + m_release_savepoint_count+= stat->m_release_savepoint_count; + } +}; + +/** Single table io statistic. */ +struct PFS_table_io_stat +{ + bool m_has_data; + /** FETCH statistics */ + PFS_single_stat m_fetch; + /** INSERT statistics */ + PFS_single_stat m_insert; + /** UPDATE statistics */ + PFS_single_stat m_update; + /** DELETE statistics */ + PFS_single_stat m_delete; + + PFS_table_io_stat() + { + m_has_data= false; + } + + inline void reset(void) + { + m_has_data= false; + m_fetch.reset(); + m_insert.reset(); + m_update.reset(); + m_delete.reset(); + } + + inline void aggregate(const PFS_table_io_stat *stat) + { + if (stat->m_has_data) + { + m_has_data= true; + m_fetch.aggregate(&stat->m_fetch); + m_insert.aggregate(&stat->m_insert); + m_update.aggregate(&stat->m_update); + m_delete.aggregate(&stat->m_delete); + } + } + + inline void sum(PFS_single_stat *result) + { + if (m_has_data) + { + result->aggregate(& m_fetch); + result->aggregate(& m_insert); + result->aggregate(& m_update); + result->aggregate(& m_delete); + } + } +}; + +enum PFS_TL_LOCK_TYPE +{ + /* Locks from enum thr_lock */ + PFS_TL_READ= 0, + PFS_TL_READ_WITH_SHARED_LOCKS= 1, + PFS_TL_READ_HIGH_PRIORITY= 2, + PFS_TL_READ_NO_INSERT= 3, + PFS_TL_WRITE_ALLOW_WRITE= 4, + PFS_TL_WRITE_CONCURRENT_INSERT= 5, + PFS_TL_WRITE_DELAYED= 6, + PFS_TL_WRITE_LOW_PRIORITY= 7, + PFS_TL_WRITE= 8, + + /* Locks for handler::ha_external_lock() */ + PFS_TL_READ_EXTERNAL= 9, + PFS_TL_WRITE_EXTERNAL= 10, + + PFS_TL_NONE= 99 +}; + +#define COUNT_PFS_TL_LOCK_TYPE 11 + +/** Statistics for table locks. */ +struct PFS_table_lock_stat +{ + PFS_single_stat m_stat[COUNT_PFS_TL_LOCK_TYPE]; + + inline void reset(void) + { + PFS_single_stat *pfs= & m_stat[0]; + PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; + for ( ; pfs < pfs_last ; pfs++) + pfs->reset(); + } + + inline void aggregate(const PFS_table_lock_stat *stat) + { + PFS_single_stat *pfs= & m_stat[0]; + PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; + const PFS_single_stat *pfs_from= & stat->m_stat[0]; + for ( ; pfs < pfs_last ; pfs++, pfs_from++) + pfs->aggregate(pfs_from); + } + + inline void sum(PFS_single_stat *result) + { + PFS_single_stat *pfs= & m_stat[0]; + PFS_single_stat *pfs_last= & m_stat[COUNT_PFS_TL_LOCK_TYPE]; + for ( ; pfs < pfs_last ; pfs++) + result->aggregate(pfs); + } +}; + +/** Statistics for TABLE usage. */ +struct PFS_table_stat +{ + /** + Statistics, per index. + Each index stat is in [0, MAX_INDEXES-1], + stats when using no index are in [MAX_INDEXES]. + */ + PFS_table_io_stat m_index_stat[MAX_INDEXES + 1]; + + /** + Statistics, per lock type. + */ + PFS_table_lock_stat m_lock_stat; + + /** Reset table io statistic. */ + inline void reset_io(void) + { + PFS_table_io_stat *stat= & m_index_stat[0]; + PFS_table_io_stat *stat_last= & m_index_stat[MAX_INDEXES + 1]; + for ( ; stat < stat_last ; stat++) + stat->reset(); + } + + /** Reset table lock statistic. */ + inline void reset_lock(void) + { + m_lock_stat.reset(); + } + + /** Reset table statistic. */ + inline void reset(void) + { + reset_io(); + reset_lock(); + } + + inline void fast_reset_io(void) + { + memcpy(& m_index_stat, & g_reset_template.m_index_stat, sizeof(m_index_stat)); + } + + inline void fast_reset_lock(void) + { + memcpy(& m_lock_stat, & g_reset_template.m_lock_stat, sizeof(m_lock_stat)); + } + + inline void fast_reset(void) + { + memcpy(this, & g_reset_template, sizeof(*this)); + } + + inline void aggregate_io(const PFS_table_stat *stat, uint key_count) + { + PFS_table_io_stat *to_stat; + PFS_table_io_stat *to_stat_last; + const PFS_table_io_stat *from_stat; + + assert(key_count <= MAX_INDEXES); + + /* Aggregate stats for each index, if any */ + to_stat= & m_index_stat[0]; + to_stat_last= to_stat + key_count; + from_stat= & stat->m_index_stat[0]; + for ( ; to_stat < to_stat_last ; from_stat++, to_stat++) + to_stat->aggregate(from_stat); + + /* Aggregate stats for the table */ + to_stat= & m_index_stat[MAX_INDEXES]; + from_stat= & stat->m_index_stat[MAX_INDEXES]; + to_stat->aggregate(from_stat); + } + + inline void aggregate_lock(const PFS_table_stat *stat) + { + m_lock_stat.aggregate(& stat->m_lock_stat); + } + + inline void aggregate(const PFS_table_stat *stat, uint key_count) + { + aggregate_io(stat, key_count); + aggregate_lock(stat); + } + + inline void sum_io(PFS_single_stat *result, uint key_count) + { + PFS_table_io_stat *stat; + PFS_table_io_stat *stat_last; + + assert(key_count <= MAX_INDEXES); + + /* Sum stats for each index, if any */ + stat= & m_index_stat[0]; + stat_last= stat + key_count; + for ( ; stat < stat_last ; stat++) + stat->sum(result); + + /* Sum stats for the table */ + m_index_stat[MAX_INDEXES].sum(result); + } + + inline void sum_lock(PFS_single_stat *result) + { + m_lock_stat.sum(result); + } + + inline void sum(PFS_single_stat *result, uint key_count) + { + sum_io(result, key_count); + sum_lock(result); + } + + static struct PFS_table_stat g_reset_template; +}; + +/** Statistics for SOCKET IO. Used for both waits and byte counts. */ +struct PFS_socket_io_stat +{ + /** READ statistics */ + PFS_byte_stat m_read; + /** WRITE statistics */ + PFS_byte_stat m_write; + /** Miscellaneous statistics */ + PFS_byte_stat m_misc; + + inline void reset(void) + { + m_read.reset(); + m_write.reset(); + m_misc.reset(); + } + + inline void aggregate(const PFS_socket_io_stat *stat) + { + m_read.aggregate(&stat->m_read); + m_write.aggregate(&stat->m_write); + m_misc.aggregate(&stat->m_misc); + } + + /* Sum waits and byte counts */ + inline void sum(PFS_byte_stat *stat) + { + stat->aggregate(&m_read); + stat->aggregate(&m_write); + stat->aggregate(&m_misc); + } + + /* Sum waits only */ + inline void sum_waits(PFS_single_stat *stat) + { + stat->aggregate(&m_read); + stat->aggregate(&m_write); + stat->aggregate(&m_misc); + } +}; + +/** Statistics for SOCKET usage. */ +struct PFS_socket_stat +{ + /** Socket timing and byte count statistics per operation */ + PFS_socket_io_stat m_io_stat; + + /** Reset socket statistics. */ + inline void reset(void) + { + m_io_stat.reset(); + } +}; + +struct PFS_memory_stat_delta +{ + size_t m_alloc_count_delta; + size_t m_free_count_delta; + size_t m_alloc_size_delta; + size_t m_free_size_delta; + + void reset() + { + m_alloc_count_delta= 0; + m_free_count_delta= 0; + m_alloc_size_delta= 0; + m_free_size_delta= 0; + } +}; + +/** + Memory statistics. + Conceptually, the following statistics are maintained: + - CURRENT_COUNT_USED, + - LOW_COUNT_USED, + - HIGH_COUNT_USED + - CURRENT_SIZE_USED, + - LOW_SIZE_USED, + - HIGH_SIZE_USED + Now, the implementation keeps different counters, + which are easier (less overhead) to maintain while + collecting statistics. + Invariants are as follows: + CURRENT_COUNT_USED = @c m_alloc_count - @c m_free_count + LOW_COUNT_USED + @c m_free_count_capacity = CURRENT_COUNT_USED + CURRENT_COUNT_USED + @c m_alloc_count_capacity = HIGH_COUNT_USED + CURRENT_SIZE_USED = @c m_alloc_size - @c m_free_size + LOW_SIZE_USED + @c m_free_size_capacity = CURRENT_SIZE_USED + CURRENT_SIZE_USED + @c m_alloc_size_capacity = HIGH_SIZE_USED + +*/ +struct PFS_memory_stat +{ + bool m_used; + size_t m_alloc_count; + size_t m_free_count; + size_t m_alloc_size; + size_t m_free_size; + + size_t m_alloc_count_capacity; + size_t m_free_count_capacity; + size_t m_alloc_size_capacity; + size_t m_free_size_capacity; + + inline void reset(void) + { + m_used= false; + m_alloc_count= 0; + m_free_count= 0; + m_alloc_size= 0; + m_free_size= 0; + + m_alloc_count_capacity= 0; + m_free_count_capacity= 0; + m_alloc_size_capacity= 0; + m_free_size_capacity= 0; + } + + inline void rebase(void) + { + if (! m_used) + return; + + size_t base; + + base= std::min<size_t>(m_alloc_count, m_free_count); + m_alloc_count-= base; + m_free_count-= base; + + base= std::min<size_t>(m_alloc_size, m_free_size); + m_alloc_size-= base; + m_free_size-= base; + + m_alloc_count_capacity= 0; + m_free_count_capacity= 0; + m_alloc_size_capacity= 0; + m_free_size_capacity= 0; + } + + inline void partial_aggregate_to(PFS_memory_stat *stat) + { + if (! m_used) + return; + + size_t base; + + stat->m_used= true; + + base= std::min<size_t>(m_alloc_count, m_free_count); + if (base != 0) + { + stat->m_alloc_count+= base; + stat->m_free_count+= base; + m_alloc_count-= base; + m_free_count-= base; + } + + base= std::min<size_t>(m_alloc_size, m_free_size); + if (base != 0) + { + stat->m_alloc_size+= base; + stat->m_free_size+= base; + m_alloc_size-= base; + m_free_size-= base; + } + + stat->m_alloc_count_capacity+= m_alloc_count_capacity; + stat->m_free_count_capacity+= m_free_count_capacity; + stat->m_alloc_size_capacity+= m_alloc_size_capacity; + stat->m_free_size_capacity+= m_free_size_capacity; + + m_alloc_count_capacity= 0; + m_free_count_capacity= 0; + m_alloc_size_capacity= 0; + m_free_size_capacity= 0; + } + + inline void full_aggregate_to(PFS_memory_stat *stat) const + { + if (! m_used) + return; + + stat->m_used= true; + + stat->m_alloc_count+= m_alloc_count; + stat->m_free_count+= m_free_count; + stat->m_alloc_size+= m_alloc_size; + stat->m_free_size+= m_free_size; + + stat->m_alloc_count_capacity+= m_alloc_count_capacity; + stat->m_free_count_capacity+= m_free_count_capacity; + stat->m_alloc_size_capacity+= m_alloc_size_capacity; + stat->m_free_size_capacity+= m_free_size_capacity; + } + + inline void partial_aggregate_to(PFS_memory_stat *stat1, PFS_memory_stat *stat2) + { + if (! m_used) + return; + + size_t base; + + stat1->m_used= true; + stat2->m_used= true; + + base= std::min<size_t>(m_alloc_count, m_free_count); + if (base != 0) + { + stat1->m_alloc_count+= base; + stat2->m_alloc_count+= base; + stat1->m_free_count+= base; + stat2->m_free_count+= base; + m_alloc_count-= base; + m_free_count-= base; + } + + base= std::min<size_t>(m_alloc_size, m_free_size); + if (base != 0) + { + stat1->m_alloc_size+= base; + stat2->m_alloc_size+= base; + stat1->m_free_size+= base; + stat2->m_free_size+= base; + m_alloc_size-= base; + m_free_size-= base; + } + + stat1->m_alloc_count_capacity+= m_alloc_count_capacity; + stat2->m_alloc_count_capacity+= m_alloc_count_capacity; + stat1->m_free_count_capacity+= m_free_count_capacity; + stat2->m_free_count_capacity+= m_free_count_capacity; + stat1->m_alloc_size_capacity+= m_alloc_size_capacity; + stat2->m_alloc_size_capacity+= m_alloc_size_capacity; + stat1->m_free_size_capacity+= m_free_size_capacity; + stat2->m_free_size_capacity+= m_free_size_capacity; + + m_alloc_count_capacity= 0; + m_free_count_capacity= 0; + m_alloc_size_capacity= 0; + m_free_size_capacity= 0; + } + + inline void full_aggregate_to(PFS_memory_stat *stat1, PFS_memory_stat *stat2) const + { + if (! m_used) + return; + + stat1->m_used= true; + stat2->m_used= true; + + stat1->m_alloc_count+= m_alloc_count; + stat2->m_alloc_count+= m_alloc_count; + stat1->m_free_count+= m_free_count; + stat2->m_free_count+= m_free_count; + stat1->m_alloc_size+= m_alloc_size; + stat2->m_alloc_size+= m_alloc_size; + stat1->m_free_size+= m_free_size; + stat2->m_free_size+= m_free_size; + + stat1->m_alloc_count_capacity+= m_alloc_count_capacity; + stat2->m_alloc_count_capacity+= m_alloc_count_capacity; + stat1->m_free_count_capacity+= m_free_count_capacity; + stat2->m_free_count_capacity+= m_free_count_capacity; + stat1->m_alloc_size_capacity+= m_alloc_size_capacity; + stat2->m_alloc_size_capacity+= m_alloc_size_capacity; + stat1->m_free_size_capacity+= m_free_size_capacity; + stat2->m_free_size_capacity+= m_free_size_capacity; + } + + void count_builtin_alloc(size_t size) + { + m_used= true; + + m_alloc_count++; + m_free_count_capacity++; + m_alloc_size+= size; + m_free_size_capacity+= size; + + if (m_alloc_count_capacity >= 1) + { + m_alloc_count_capacity--; + } + + if (m_alloc_size_capacity >= size) + { + m_alloc_size_capacity-= size; + } + + return; + } + + void count_builtin_free(size_t size) + { + m_used= true; + + m_free_count++; + m_alloc_count_capacity++; + m_free_size+= size; + m_alloc_size_capacity+= size; + + if (m_free_count_capacity >= 1) + { + m_free_count_capacity--; + } + + if (m_free_size_capacity >= size) + { + m_free_size_capacity-= size; + } + + return; + } + + inline PFS_memory_stat_delta *count_alloc(size_t size, + PFS_memory_stat_delta *delta) + { + m_used= true; + + m_alloc_count++; + m_free_count_capacity++; + m_alloc_size+= size; + m_free_size_capacity+= size; + + if ((m_alloc_count_capacity >= 1) && + (m_alloc_size_capacity >= size)) + { + m_alloc_count_capacity--; + m_alloc_size_capacity-= size; + return NULL; + } + + delta->reset(); + + if (m_alloc_count_capacity >= 1) + { + m_alloc_count_capacity--; + } + else + { + delta->m_alloc_count_delta= 1; + } + + if (m_alloc_size_capacity >= size) + { + m_alloc_size_capacity-= size; + } + else + { + delta->m_alloc_size_delta= size - m_alloc_size_capacity; + m_alloc_size_capacity= 0; + } + + return delta; + } + + inline PFS_memory_stat_delta *count_realloc(size_t old_size, size_t new_size, + PFS_memory_stat_delta *delta) + { + m_used= true; + + size_t size_delta= new_size - old_size; + m_alloc_count++; + m_alloc_size+= new_size; + m_free_count++; + m_free_size+= old_size; + + if (new_size == old_size) + { + return NULL; + } + + if (new_size > old_size) + { + /* Growing */ + size_delta= new_size - old_size; + m_free_size_capacity+= size_delta; + + if (m_alloc_size_capacity >= size_delta) + { + m_alloc_size_capacity-= size_delta; + return NULL; + } + + delta->reset(); + delta->m_alloc_size_delta= size_delta - m_alloc_size_capacity; + m_alloc_size_capacity= 0; + } + else + { + /* Shrinking */ + size_delta= old_size - new_size; + m_alloc_size_capacity+= size_delta; + + if (m_free_size_capacity >= size_delta) + { + m_free_size_capacity-= size_delta; + return NULL; + } + + delta->reset(); + delta->m_free_size_delta= size_delta - m_free_size_capacity; + m_free_size_capacity= 0; + } + + return delta; + } + + inline PFS_memory_stat_delta *count_free(size_t size, PFS_memory_stat_delta *delta) + { + m_used= true; + + m_free_count++; + m_alloc_count_capacity++; + m_free_size+= size; + m_alloc_size_capacity+= size; + + if ((m_free_count_capacity >= 1) && + (m_free_size_capacity >= size)) + { + m_free_count_capacity--; + m_free_size_capacity-= size; + return NULL; + } + + delta->reset(); + + if (m_free_count_capacity >= 1) + { + m_free_count_capacity--; + } + else + { + delta->m_free_count_delta= 1; + } + + if (m_free_size_capacity >= size) + { + m_free_size_capacity-= size; + } + else + { + delta->m_free_size_delta= size - m_free_size_capacity; + m_free_size_capacity= 0; + } + + return delta; + } + + inline PFS_memory_stat_delta *apply_delta(const PFS_memory_stat_delta *delta, + PFS_memory_stat_delta *delta_buffer) + { + size_t val; + size_t remaining_alloc_count; + size_t remaining_alloc_size; + size_t remaining_free_count; + size_t remaining_free_size; + bool has_remaining= false; + + m_used= true; + + val= delta->m_alloc_count_delta; + if (val <= m_alloc_count_capacity) + { + m_alloc_count_capacity-= val; + remaining_alloc_count= 0; + } + else + { + remaining_alloc_count= val - m_alloc_count_capacity; + m_alloc_count_capacity= 0; + has_remaining= true; + } + + val= delta->m_alloc_size_delta; + if (val <= m_alloc_size_capacity) + { + m_alloc_size_capacity-= val; + remaining_alloc_size= 0; + } + else + { + remaining_alloc_size= val - m_alloc_size_capacity; + m_alloc_size_capacity= 0; + has_remaining= true; + } + + val= delta->m_free_count_delta; + if (val <= m_free_count_capacity) + { + m_free_count_capacity-= val; + remaining_free_count= 0; + } + else + { + remaining_free_count= val - m_free_count_capacity; + m_free_count_capacity= 0; + has_remaining= true; + } + + val= delta->m_free_size_delta; + if (val <= m_free_size_capacity) + { + m_free_size_capacity-= val; + remaining_free_size= 0; + } + else + { + remaining_free_size= val - m_free_size_capacity; + m_free_size_capacity= 0; + has_remaining= true; + } + + if (! has_remaining) + return NULL; + + delta_buffer->m_alloc_count_delta= remaining_alloc_count; + delta_buffer->m_alloc_size_delta= remaining_alloc_size; + delta_buffer->m_free_count_delta= remaining_free_count; + delta_buffer->m_free_size_delta= remaining_free_size; + return delta_buffer; + } +}; + +#define PFS_MEMORY_STAT_INITIALIZER { false, 0, 0, 0, 0, 0, 0, 0, 0} + +/** Connections statistics. */ +struct PFS_connection_stat +{ + PFS_connection_stat() + : m_current_connections(0), + m_total_connections(0) + {} + + ulonglong m_current_connections; + ulonglong m_total_connections; + + inline void aggregate_active(ulonglong active) + { + m_current_connections+= active; + m_total_connections+= active; + } + + inline void aggregate_disconnected(ulonglong disconnected) + { + m_total_connections+= disconnected; + } +}; + +/** @} */ +#endif + |