From 8f20634d9c6189c60b6990c139fcd48bce18e832 Mon Sep 17 00:00:00 2001 From: Dmitry Yemanov Date: Sun, 21 Sep 2025 11:10:22 +0300 Subject: [PATCH] Refactor RuntimeStatistics to make it more extendable for future counters (including grouped ones) --- src/jrd/Attachment.cpp | 8 +- src/jrd/Monitoring.cpp | 70 +++---- src/jrd/RuntimeStatistics.cpp | 117 +++++++---- src/jrd/RuntimeStatistics.h | 354 ++++++++++++++++++-------------- src/jrd/cch.cpp | 18 +- src/jrd/inf.cpp | 33 ++- src/jrd/jrd.h | 24 +-- src/jrd/recsrc/SortedStream.cpp | 5 +- src/jrd/tra.cpp | 15 +- src/jrd/trace/TraceObjects.cpp | 2 +- src/jrd/trace/TraceObjects.h | 2 +- src/jrd/vio.cpp | 69 +++---- 12 files changed, 391 insertions(+), 326 deletions(-) diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 72e83efae5b..3222bb1a742 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -632,10 +632,12 @@ void Jrd::Attachment::signalShutdown(ISC_STATUS code) void Jrd::Attachment::mergeStats(bool pageStatsOnly) { MutexLockGuard guard(att_database->dbb_stats_mutex, FB_FUNCTION); - att_database->dbb_stats.adjustPageStats(att_base_stats, att_stats); - if (!pageStatsOnly) + + if (pageStatsOnly) + att_database->dbb_stats.adjustPageStats(att_base_stats, att_stats); + else { - att_database->dbb_stats.adjust(att_base_stats, att_stats, true); + att_database->dbb_stats.adjust(att_base_stats, att_stats); att_base_stats.assign(att_stats); } } diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index 223ddc5edf3..ea09c3daa32 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -1422,36 +1422,36 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt record.reset(rel_mon_io_stats); record.storeGlobalId(f_mon_io_stat_id, id); record.storeInteger(f_mon_io_stat_group, stat_group); - record.storeInteger(f_mon_io_page_reads, statistics.getValue(RuntimeStatistics::PAGE_READS)); - record.storeInteger(f_mon_io_page_writes, statistics.getValue(RuntimeStatistics::PAGE_WRITES)); - record.storeInteger(f_mon_io_page_fetches, statistics.getValue(RuntimeStatistics::PAGE_FETCHES)); - record.storeInteger(f_mon_io_page_marks, statistics.getValue(RuntimeStatistics::PAGE_MARKS)); + record.storeInteger(f_mon_io_page_reads, statistics[PageStatType::READS]); + record.storeInteger(f_mon_io_page_writes, statistics[PageStatType::WRITES]); + record.storeInteger(f_mon_io_page_fetches, statistics[PageStatType::FETCHES]); + record.storeInteger(f_mon_io_page_marks, statistics[PageStatType::MARKS]); record.write(); // logical I/O statistics (global) record.reset(rel_mon_rec_stats); record.storeGlobalId(f_mon_rec_stat_id, id); record.storeInteger(f_mon_rec_stat_group, stat_group); - record.storeInteger(f_mon_rec_seq_reads, statistics.getValue(RuntimeStatistics::RECORD_SEQ_READS)); - record.storeInteger(f_mon_rec_idx_reads, statistics.getValue(RuntimeStatistics::RECORD_IDX_READS)); - record.storeInteger(f_mon_rec_inserts, statistics.getValue(RuntimeStatistics::RECORD_INSERTS)); - record.storeInteger(f_mon_rec_updates, statistics.getValue(RuntimeStatistics::RECORD_UPDATES)); - record.storeInteger(f_mon_rec_deletes, statistics.getValue(RuntimeStatistics::RECORD_DELETES)); - record.storeInteger(f_mon_rec_backouts, statistics.getValue(RuntimeStatistics::RECORD_BACKOUTS)); - record.storeInteger(f_mon_rec_purges, statistics.getValue(RuntimeStatistics::RECORD_PURGES)); - record.storeInteger(f_mon_rec_expunges, statistics.getValue(RuntimeStatistics::RECORD_EXPUNGES)); - record.storeInteger(f_mon_rec_locks, statistics.getValue(RuntimeStatistics::RECORD_LOCKS)); - record.storeInteger(f_mon_rec_waits, statistics.getValue(RuntimeStatistics::RECORD_WAITS)); - record.storeInteger(f_mon_rec_conflicts, statistics.getValue(RuntimeStatistics::RECORD_CONFLICTS)); - record.storeInteger(f_mon_rec_bkver_reads, statistics.getValue(RuntimeStatistics::RECORD_BACKVERSION_READS)); - record.storeInteger(f_mon_rec_frg_reads, statistics.getValue(RuntimeStatistics::RECORD_FRAGMENT_READS)); - record.storeInteger(f_mon_rec_rpt_reads, statistics.getValue(RuntimeStatistics::RECORD_RPT_READS)); - record.storeInteger(f_mon_rec_imgc, statistics.getValue(RuntimeStatistics::RECORD_IMGC)); + record.storeInteger(f_mon_rec_seq_reads, statistics[RecordStatType::SEQ_READS]); + record.storeInteger(f_mon_rec_idx_reads, statistics[RecordStatType::IDX_READS]); + record.storeInteger(f_mon_rec_inserts, statistics[RecordStatType::INSERTS]); + record.storeInteger(f_mon_rec_updates, statistics[RecordStatType::UPDATES]); + record.storeInteger(f_mon_rec_deletes, statistics[RecordStatType::DELETES]); + record.storeInteger(f_mon_rec_backouts, statistics[RecordStatType::BACKOUTS]); + record.storeInteger(f_mon_rec_purges, statistics[RecordStatType::PURGES]); + record.storeInteger(f_mon_rec_expunges, statistics[RecordStatType::EXPUNGES]); + record.storeInteger(f_mon_rec_locks, statistics[RecordStatType::LOCKS]); + record.storeInteger(f_mon_rec_waits, statistics[RecordStatType::WAITS]); + record.storeInteger(f_mon_rec_conflicts, statistics[RecordStatType::CONFLICTS]); + record.storeInteger(f_mon_rec_bkver_reads, statistics[RecordStatType::BACK_READS]); + record.storeInteger(f_mon_rec_frg_reads, statistics[RecordStatType::FRAGMENT_READS]); + record.storeInteger(f_mon_rec_rpt_reads, statistics[RecordStatType::RPT_READS]); + record.storeInteger(f_mon_rec_imgc, statistics[RecordStatType::IMGC]); record.write(); // logical I/O statistics (table wise) - for (RuntimeStatistics::Iterator iter = statistics.begin(); iter != statistics.end(); ++iter) + for (auto iter(statistics.getRelCounters()); iter; ++iter) { const auto rec_stat_id = getGlobalId(fb_utils::genUniqueId()); @@ -1466,21 +1466,21 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt record.reset(rel_mon_rec_stats); record.storeGlobalId(f_mon_rec_stat_id, rec_stat_id); record.storeInteger(f_mon_rec_stat_group, stat_group); - record.storeInteger(f_mon_rec_seq_reads, (*iter).getCounter(RuntimeStatistics::RECORD_SEQ_READS)); - record.storeInteger(f_mon_rec_idx_reads, (*iter).getCounter(RuntimeStatistics::RECORD_IDX_READS)); - record.storeInteger(f_mon_rec_inserts, (*iter).getCounter(RuntimeStatistics::RECORD_INSERTS)); - record.storeInteger(f_mon_rec_updates, (*iter).getCounter(RuntimeStatistics::RECORD_UPDATES)); - record.storeInteger(f_mon_rec_deletes, (*iter).getCounter(RuntimeStatistics::RECORD_DELETES)); - record.storeInteger(f_mon_rec_backouts, (*iter).getCounter(RuntimeStatistics::RECORD_BACKOUTS)); - record.storeInteger(f_mon_rec_purges, (*iter).getCounter(RuntimeStatistics::RECORD_PURGES)); - record.storeInteger(f_mon_rec_expunges, (*iter).getCounter(RuntimeStatistics::RECORD_EXPUNGES)); - record.storeInteger(f_mon_rec_locks, (*iter).getCounter(RuntimeStatistics::RECORD_LOCKS)); - record.storeInteger(f_mon_rec_waits, (*iter).getCounter(RuntimeStatistics::RECORD_WAITS)); - record.storeInteger(f_mon_rec_conflicts, (*iter).getCounter(RuntimeStatistics::RECORD_CONFLICTS)); - record.storeInteger(f_mon_rec_bkver_reads, (*iter).getCounter(RuntimeStatistics::RECORD_BACKVERSION_READS)); - record.storeInteger(f_mon_rec_frg_reads, (*iter).getCounter(RuntimeStatistics::RECORD_FRAGMENT_READS)); - record.storeInteger(f_mon_rec_rpt_reads, (*iter).getCounter(RuntimeStatistics::RECORD_RPT_READS)); - record.storeInteger(f_mon_rec_imgc, (*iter).getCounter(RuntimeStatistics::RECORD_IMGC)); + record.storeInteger(f_mon_rec_seq_reads, (*iter)[RecordStatType::SEQ_READS]); + record.storeInteger(f_mon_rec_idx_reads, (*iter)[RecordStatType::IDX_READS]); + record.storeInteger(f_mon_rec_inserts, (*iter)[RecordStatType::INSERTS]); + record.storeInteger(f_mon_rec_updates, (*iter)[RecordStatType::UPDATES]); + record.storeInteger(f_mon_rec_deletes, (*iter)[RecordStatType::DELETES]); + record.storeInteger(f_mon_rec_backouts, (*iter)[RecordStatType::BACKOUTS]); + record.storeInteger(f_mon_rec_purges, (*iter)[RecordStatType::PURGES]); + record.storeInteger(f_mon_rec_expunges, (*iter)[RecordStatType::EXPUNGES]); + record.storeInteger(f_mon_rec_locks, (*iter)[RecordStatType::LOCKS]); + record.storeInteger(f_mon_rec_waits, (*iter)[RecordStatType::WAITS]); + record.storeInteger(f_mon_rec_conflicts, (*iter)[RecordStatType::CONFLICTS]); + record.storeInteger(f_mon_rec_bkver_reads, (*iter)[RecordStatType::BACK_READS]); + record.storeInteger(f_mon_rec_frg_reads, (*iter)[RecordStatType::FRAGMENT_READS]); + record.storeInteger(f_mon_rec_rpt_reads, (*iter)[RecordStatType::RPT_READS]); + record.storeInteger(f_mon_rec_imgc, (*iter)[RecordStatType::IMGC]); record.write(); } } diff --git a/src/jrd/RuntimeStatistics.cpp b/src/jrd/RuntimeStatistics.cpp index cdc4e4b0923..95630662623 100644 --- a/src/jrd/RuntimeStatistics.cpp +++ b/src/jrd/RuntimeStatistics.cpp @@ -33,47 +33,58 @@ namespace Jrd { GlobalPtr RuntimeStatistics::dummy; -void RuntimeStatistics::findAndBumpRelValue(const StatType index, SLONG relation_id, SINT64 delta) +void RuntimeStatistics::adjustRelStats(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) { - if (rel_counts.find(relation_id, rel_last_pos)) - rel_counts[rel_last_pos].bumpCounter(index, delta); - else - { - RelationCounts counts(relation_id); - counts.bumpCounter(index, delta); - rel_counts.insert(rel_last_pos, counts); - } -} - -void RuntimeStatistics::addRelCounts(const RelCounters& other, bool add) -{ - if (other.isEmpty()) + if (baseStats.relChgNumber == newStats.relChgNumber) return; - RelCounters::const_iterator src(other.begin()); - const RelCounters::const_iterator end(other.end()); + relChgNumber++; - FB_SIZE_T pos; - rel_counts.find(src->getRelationId(), pos); - for (; src != end; ++src) + auto locate = [this](SLONG relId) -> FB_SIZE_T { - const FB_SIZE_T cnt = rel_counts.getCount(); + FB_SIZE_T pos; + if (!rel_counts.find(relId, pos)) + rel_counts.insert(pos, RelationCounts(relId)); + return pos; + }; - while (pos < cnt && rel_counts[pos].getRelationId() < src->getRelationId()) - pos++; + auto baseIter = baseStats.rel_counts.begin(), newIter = newStats.rel_counts.begin(); + const auto baseEnd = baseStats.rel_counts.end(), newEnd = newStats.rel_counts.end(); - if (pos >= cnt || rel_counts[pos].getRelationId() > src->getRelationId()) + // The loop below assumes that newStats cannot miss relations existing in baseStats, + // this must be always the case as long as newStats is an incremented version of baseStats + + while (newIter != newEnd || baseIter != baseEnd) + { + if (baseIter == baseEnd) { - RelationCounts counts(src->getRelationId()); - rel_counts.insert(pos, counts); + // Relation exists in newStats but missing in baseStats + const auto newRelId = newIter->getRelationId(); + rel_counts[locate(newRelId)] += *newIter++; } + else if (newIter != newEnd) + { + const auto baseRelId = baseIter->getRelationId(); + const auto newRelId = newIter->getRelationId(); - fb_assert(pos >= 0 && pos < rel_counts.getCount()); - - if (add) - rel_counts[pos] += *src; + if (newRelId == baseRelId) + { + // Relation exists in both newStats and baseStats + fb_assert(baseRelId == newRelId); + const auto pos = locate(baseRelId); + rel_counts[pos] -= *baseIter++; + rel_counts[pos] += *newIter++; + } + else if (newRelId < baseRelId) + { + // Relation exists in newStats but missing in baseStats + rel_counts[locate(newRelId)] += *newIter++; + } + else + fb_assert(false); // should never happen + } else - rel_counts[pos] -= *src; + fb_assert(false); // should never happen } } @@ -86,7 +97,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, // NOTE: we do not initialize dest.pin_time. This must be done by the caller // Calculate database-level statistics - for (int i = 0; i < TOTAL_ITEMS; i++) + for (size_t i = 0; i < GLOBAL_ITEMS; i++) values[i] = new_stat.values[i] - values[i]; dest.pin_counters = values; @@ -99,16 +110,14 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, RelCounters::iterator base_cnts = rel_counts.begin(); bool base_found = (base_cnts != rel_counts.end()); - RelCounters::const_iterator new_cnts = new_stat.rel_counts.begin(); - const RelCounters::const_iterator end = new_stat.rel_counts.end(); - for (; new_cnts != end; ++new_cnts) + for (const auto& new_cnts : new_stat.rel_counts) { - const SLONG rel_id = new_cnts->getRelationId(); + const SLONG rel_id = new_cnts.getRelationId(); if (base_found && base_cnts->getRelationId() == rel_id) { // Point TraceCounts to counts array from baseline object - if (base_cnts->setToDiff(*new_cnts)) + if (base_cnts->setToDiff(new_cnts)) { jrd_rel* const relation = rel_id < static_cast(att->att_relations->count()) ? @@ -142,7 +151,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, // Point TraceCounts to counts array from object with updated counters TraceCounts traceCounts; traceCounts.trc_relation_id = rel_id; - traceCounts.trc_counters = new_cnts->getCounterVector(); + traceCounts.trc_counters = new_cnts.getCounterVector(); if (relation) { @@ -163,14 +172,42 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, return &dest; } -RuntimeStatistics::Accumulator::Accumulator(thread_db* tdbb, const jrd_rel* relation, StatType type) - : m_tdbb(tdbb), m_type(type), m_id(relation->rel_id), m_counter(0) +void RuntimeStatistics::adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) +{ + if (baseStats.allChgNumber == newStats.allChgNumber) + return; + + allChgNumber++; + for (size_t i = 0; i < GLOBAL_ITEMS; ++i) + values[i] += newStats.values[i] - baseStats.values[i]; + + adjustRelStats(baseStats, newStats); +} + +void RuntimeStatistics::adjustPageStats(RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) +{ + if (baseStats.allChgNumber == newStats.allChgNumber) + return; + + allChgNumber++; + for (size_t i = 0; i < PAGE_TOTAL_ITEMS; ++i) + { + const SINT64 delta = newStats.values[i] - baseStats.values[i]; + + values[i] += delta; + baseStats.values[i] += delta; + } +} + +RuntimeStatistics::Accumulator::Accumulator(thread_db* tdbb, const jrd_rel* relation, + const RecordStatType type) + : m_tdbb(tdbb), m_type(type), m_id(relation->rel_id) {} RuntimeStatistics::Accumulator::~Accumulator() { if (m_counter) - m_tdbb->bumpRelStats(m_type, m_id, m_counter); + m_tdbb->bumpStats(m_type, m_id, m_counter); } } // namespace diff --git a/src/jrd/RuntimeStatistics.h b/src/jrd/RuntimeStatistics.h index 2c34096be6c..8afab2619bc 100644 --- a/src/jrd/RuntimeStatistics.h +++ b/src/jrd/RuntimeStatistics.h @@ -28,6 +28,9 @@ #include "../common/classes/objects_array.h" #include "../common/classes/init.h" #include "../common/classes/tree.h" +#include "../common/classes/File.h" + +#include namespace Firebird { @@ -48,82 +51,135 @@ class jrd_rel; typedef Firebird::HalfStaticArray TraceCountsArray; -// Runtime statistics class +// Runtime statistics + +enum class PageStatType +{ + FETCHES = 0, + READS, + MARKS, + WRITES, + TOTAL_ITEMS +}; + +enum class RecordStatType +{ + SEQ_READS = 0, + IDX_READS, + UPDATES, + INSERTS, + DELETES, + BACKOUTS, + PURGES, + EXPUNGES, + LOCKS, + WAITS, + CONFLICTS, + BACK_READS, + FRAGMENT_READS, + RPT_READS, + IMGC, + TOTAL_ITEMS +}; class RuntimeStatistics : protected Firebird::AutoStorage { + static constexpr size_t PAGE_TOTAL_ITEMS = static_cast(PageStatType::TOTAL_ITEMS); + static constexpr size_t RECORD_TOTAL_ITEMS = static_cast(RecordStatType::TOTAL_ITEMS); + public: - enum StatType { - PAGE_FETCHES = 0, - PAGE_READS, - PAGE_MARKS, - PAGE_WRITES, - RECORD_FIRST_ITEM, - RECORD_SEQ_READS = RECORD_FIRST_ITEM, - RECORD_IDX_READS, - RECORD_UPDATES, - RECORD_INSERTS, - RECORD_DELETES, - RECORD_BACKOUTS, - RECORD_PURGES, - RECORD_EXPUNGES, - RECORD_LOCKS, - RECORD_WAITS, - RECORD_CONFLICTS, - RECORD_BACKVERSION_READS, - RECORD_FRAGMENT_READS, - RECORD_RPT_READS, - RECORD_IMGC, - RECORD_LAST_ITEM = RECORD_IMGC, - TOTAL_ITEMS // last - }; + // Number of globally counted items. + // + // dimitr: Currently, they include page-level and record-level counters. + // However, this is not strictly required to maintain global record-level counters, + // as they may be aggregated from the rel_counts array on demand. This would slow down + // the retrieval of counters but save some CPU cycles inside tdbb->bumpStats(). + // As long as public struct PerformanceInfo don't include record-level counters, + // this is not going to affect any existing applications/plugins. + // So far I leave everything as is but it can be reconsidered in the future. + // sumValue() method is already in place for that purpose. + // + static constexpr size_t GLOBAL_ITEMS = PAGE_TOTAL_ITEMS + RECORD_TOTAL_ITEMS; private: - static const size_t REL_BASE_OFFSET = RECORD_FIRST_ITEM; - static const size_t REL_TOTAL_ITEMS = RECORD_LAST_ITEM - REL_BASE_OFFSET + 1; - - // Performance counters for individual table - - class RelationCounts + template class CountsVector { + static constexpr size_t SIZE = static_cast(T::TOTAL_ITEMS); + public: - explicit RelationCounts(SLONG relation_id) - : rlc_relation_id(relation_id) + CountsVector() = default; + + SINT64& operator[](const T index) { - memset(rlc_counter, 0, sizeof(rlc_counter)); + return m_counters[static_cast(index)]; } - SLONG getRelationId() const + const SINT64& operator[](const T index) const + { + return m_counters[static_cast(index)]; + } + + CountsVector& operator+=(const CountsVector& other) + { + for (size_t i = 0; i < m_counters.size(); i++) + m_counters[i] += other.m_counters[i]; + + return *this; + } + + CountsVector& operator-=(const CountsVector& other) { - return rlc_relation_id; + for (size_t i = 0; i < m_counters.size(); i++) + m_counters[i] -= other.m_counters[i]; + + return *this; } const SINT64* getCounterVector() const { - return rlc_counter; + return m_counters.data(); } - SINT64 getCounter(size_t index) const + bool isEmpty() const { - fb_assert(index >= REL_BASE_OFFSET && index < REL_BASE_OFFSET + REL_TOTAL_ITEMS); - return rlc_counter[index - REL_BASE_OFFSET]; + return std::all_of(m_counters.begin(), m_counters.end(), + [](SINT64 value) { return value == 0; }); } - void bumpCounter(size_t index, SINT64 delta = 1) + bool hasData() const { - fb_assert(index >= REL_BASE_OFFSET && index < REL_BASE_OFFSET + REL_TOTAL_ITEMS); - rlc_counter[index - REL_BASE_OFFSET] += delta; + return std::any_of(m_counters.begin(), m_counters.end(), + [](SINT64 value) { return value != 0; }); + } + + protected: + std::array m_counters = {}; + }; + + // Performance counters for individual table + + class RelationCounts : public CountsVector + { + public: + explicit RelationCounts(SLONG relation_id) + : m_relation_id(relation_id) + { + } + + SLONG getRelationId() const + { + return m_relation_id; } bool setToDiff(const RelationCounts& other) { - fb_assert(rlc_relation_id == other.rlc_relation_id); + fb_assert(m_relation_id == other.m_relation_id); bool ret = false; - for (size_t i = 0; i < REL_TOTAL_ITEMS; i++) + for (size_t i = 0; i < m_counters.size(); i++) { - if ( (rlc_counter[i] = other.rlc_counter[i] - rlc_counter[i]) ) + if ( (m_counters[i] = other.m_counters[i] - m_counters[i]) ) ret = true; } @@ -132,32 +188,25 @@ class RuntimeStatistics : protected Firebird::AutoStorage RelationCounts& operator+=(const RelationCounts& other) { - fb_assert(rlc_relation_id == other.rlc_relation_id); - - for (size_t i = 0; i < REL_TOTAL_ITEMS; i++) - rlc_counter[i] += other.rlc_counter[i]; - + fb_assert(m_relation_id == other.m_relation_id); + CountsVector::operator+=(other); return *this; } RelationCounts& operator-=(const RelationCounts& other) { - fb_assert(rlc_relation_id == other.rlc_relation_id); - - for (size_t i = 0; i < REL_TOTAL_ITEMS; i++) - rlc_counter[i] -= other.rlc_counter[i]; - + fb_assert(m_relation_id == other.m_relation_id); + CountsVector::operator-=(other); return *this; } inline static const SLONG& generate(const RelationCounts& item) { - return item.rlc_relation_id; + return item.m_relation_id; } private: - SLONG rlc_relation_id; - SINT64 rlc_counter[REL_TOTAL_ITEMS]; + SLONG m_relation_id; }; typedef Firebird::SortedArray, @@ -196,7 +245,7 @@ class RuntimeStatistics : protected Firebird::AutoStorage relChgNumber = other.relChgNumber; } - ~RuntimeStatistics() {} + ~RuntimeStatistics() = default; void reset() { @@ -207,92 +256,86 @@ class RuntimeStatistics : protected Firebird::AutoStorage relChgNumber = 0; } - SINT64 getValue(const StatType index) const + const SINT64& operator[](const PageStatType type) const { + const auto index = static_cast(type); return values[index]; } - void bumpValue(const StatType index, SINT64 delta = 1) + void bumpValue(const PageStatType type, SINT64 delta = 1) { + const auto index = static_cast(type); values[index] += delta; ++allChgNumber; } - SINT64 getRelValue(const StatType index, SLONG relation_id) const + const SINT64& operator[](const RecordStatType type) const { - FB_SIZE_T pos; - return rel_counts.find(relation_id, pos) ? rel_counts[pos].getCounter(index) : 0; + const auto index = static_cast(type); + return values[PAGE_TOTAL_ITEMS + index]; + } + + SINT64 sumValue(const RecordStatType type) const + { + SINT64 value = 0; + + for (const auto& counts : rel_counts) + value += counts[type]; + + return value; } - void bumpRelValue(const StatType index, SLONG relation_id, SINT64 delta = 1) + void bumpValue(const RecordStatType type, SINT64 delta = 1) { - fb_assert(index >= 0); + const auto index = static_cast(type); + values[PAGE_TOTAL_ITEMS + index] += delta; + ++allChgNumber; + } + + void bumpValue(const RecordStatType type, SLONG relation_id, SINT64 delta = 1) + { + ++allChgNumber; ++relChgNumber; - if (rel_last_pos != (FB_SIZE_T)~0 && rel_counts[rel_last_pos].getRelationId() == relation_id) - rel_counts[rel_last_pos].bumpCounter(index, delta); + if ((rel_last_pos != (FB_SIZE_T)~0 && rel_counts[rel_last_pos].getRelationId() == relation_id) || + // if rel_last_pos is mispositioned + rel_counts.find(relation_id, rel_last_pos)) + { + rel_counts[rel_last_pos][type] += delta; + } else - findAndBumpRelValue(index, relation_id, delta); + { + RelationCounts counts(relation_id); + counts[type] += delta; + rel_counts.insert(rel_last_pos, counts); + } } - void findAndBumpRelValue(const StatType index, SLONG relation_id, SINT64 delta); - // Calculate difference between counts stored in this object and current // counts of given request. Counts stored in object are destroyed. Firebird::PerformanceInfo* computeDifference(Attachment* att, const RuntimeStatistics& new_stat, Firebird::PerformanceInfo& dest, TraceCountsArray& temp, Firebird::ObjectsArray& tempNames); - // add difference between newStats and baseStats to our counters - // newStats and baseStats must be "in-sync" - void adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats, bool relStatsOnly = false) - { - if (baseStats.allChgNumber != newStats.allChgNumber) - { - const size_t FIRST_ITEM = relStatsOnly ? REL_BASE_OFFSET : 0; - - allChgNumber++; - for (size_t i = FIRST_ITEM; i < TOTAL_ITEMS; ++i) - values[i] += newStats.values[i] - baseStats.values[i]; + // Add difference between newStats and baseStats to our counters + // (newStats and baseStats must be "in-sync") + void adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats); - if (baseStats.relChgNumber != newStats.relChgNumber) - { - relChgNumber++; - addRelCounts(newStats.rel_counts, true); - addRelCounts(baseStats.rel_counts, false); - } - } - } + void adjustPageStats(RuntimeStatistics& baseStats, const RuntimeStatistics& newStats); - void adjustPageStats(RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) - { - if (baseStats.allChgNumber != newStats.allChgNumber) - { - allChgNumber++; - for (size_t i = 0; i < REL_BASE_OFFSET; ++i) - { - const SINT64 delta = newStats.values[i] - baseStats.values[i]; - - values[i] += delta; - baseStats.values[i] += delta; - } - } - } - - // copy counters values from other instance - // after copying both instances are "in-sync" i.e. have the same - // allChgNumber and relChgNumber values + // Copy counters values from other instance. + // After copying both instances are "in-sync" i.e. have the same change numbers. RuntimeStatistics& assign(const RuntimeStatistics& other) { if (allChgNumber != other.allChgNumber) { memcpy(values, other.values, sizeof(values)); allChgNumber = other.allChgNumber; - } - if (relChgNumber != other.relChgNumber) - { - rel_counts = other.rel_counts; - relChgNumber = other.relChgNumber; + if (relChgNumber != other.relChgNumber) + { + rel_counts = other.rel_counts; + relChgNumber = other.relChgNumber; + } } return *this; @@ -303,76 +346,75 @@ class RuntimeStatistics : protected Firebird::AutoStorage return &dummy; } - class Iterator + class Accumulator { - friend class RuntimeStatistics; + public: + Accumulator(thread_db* tdbb, const jrd_rel* relation, const RecordStatType type); + ~Accumulator(); + + void operator++() + { + m_counter++; + } - explicit Iterator(const RelationCounts* counts) - : m_counts(counts) - {} + private: + thread_db* const m_tdbb; + const RecordStatType m_type; + const SLONG m_id; + SINT64 m_counter = 0; + }; + template class Iterator + { public: - bool operator==(const Iterator& other) const + explicit Iterator(const T& counts) + : m_iter(counts.begin()), m_end(counts.end()) { - return (m_counts == other.m_counts); + advance(); } - bool operator!=(const Iterator& other) const + void operator++() { - return (m_counts != other.m_counts); + m_iter++; + advance(); } - Iterator& operator++() + T::const_reference operator*() const { - m_counts++; - return *this; + return *m_iter; } - const RelationCounts& operator*() const + operator bool() const { - return *m_counts; + return (m_iter != m_end); } private: - const RelationCounts* m_counts; + T::const_iterator m_iter; + const T::const_iterator m_end; + + void advance() + { + while (m_iter != m_end && m_iter->isEmpty()) + m_iter++; + } }; - Iterator begin() const - { - return Iterator(rel_counts.begin()); - } + typedef Iterator RelationIterator; - Iterator end() const + RelationIterator getRelCounters() const { - return Iterator(rel_counts.end()); + return RelationIterator(rel_counts); } - class Accumulator - { - public: - Accumulator(thread_db* tdbb, const jrd_rel* relation, StatType type); - ~Accumulator(); - - void operator++() - { - m_counter++; - } - - private: - thread_db* m_tdbb; - StatType m_type; - SLONG m_id; - SINT64 m_counter; - }; - private: - void addRelCounts(const RelCounters& other, bool add); + void adjustRelStats(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats); - SINT64 values[TOTAL_ITEMS]; + SINT64 values[GLOBAL_ITEMS]; RelCounters rel_counts; FB_SIZE_T rel_last_pos; - // These two numbers are used in adjust() and assign() methods as "generation" + // These three numbers are used in adjust() and assign() methods as "generation" // values in order to avoid costly operations when two instances of RuntimeStatistics // contain equal counters values. This is intended to use *only* with the // same pair of class instances, as in Request. diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp index f8c0dac2034..d660ce17bf1 100644 --- a/src/jrd/cch.cpp +++ b/src/jrd/cch.cpp @@ -930,7 +930,7 @@ void CCH_fetch_page(thread_db* tdbb, WIN* window, const bool read_shadow) pag* page = bdb->bdb_buffer; bdb->bdb_incarnation = ++bcb->bcb_page_incarnation; - tdbb->bumpStats(RuntimeStatistics::PAGE_READS); + tdbb->bumpStats(PageStatType::READS); PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(bdb->bdb_page.getPageSpaceID()); fb_assert(pageSpace); @@ -1701,7 +1701,7 @@ void CCH_mark(thread_db* tdbb, WIN* window, bool mark_system, bool must_write) SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); - tdbb->bumpStats(RuntimeStatistics::PAGE_MARKS); + tdbb->bumpStats(PageStatType::MARKS); BufferControl* bcb = dbb->dbb_bcb; @@ -3640,7 +3640,7 @@ static BufferDesc* get_dirty_buffer(thread_db* tdbb) if (bdb->bdb_flags & BDB_db_dirty) { - //tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); shouldn't it be here? + //tdbb->bumpStats(PageStatType::FETCHES); shouldn't it be here? return bdb; } @@ -3814,7 +3814,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s if (bdb->bdb_page == page) { recentlyUsed(bdb); - tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); + tdbb->bumpStats(PageStatType::FETCHES); return bdb; } @@ -3857,7 +3857,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s if (bdb->bdb_page == page) { recentlyUsed(bdb); - tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); + tdbb->bumpStats(PageStatType::FETCHES); cacheBuffer(att, bdb); return bdb; } @@ -3897,7 +3897,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s { bdb->downgrade(syncType); recentlyUsed(bdb); - tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); + tdbb->bumpStats(PageStatType::FETCHES); cacheBuffer(att, bdb); return bdb; } @@ -3941,7 +3941,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s else recentlyUsed(bdb); } - tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); + tdbb->bumpStats(PageStatType::FETCHES); cacheBuffer(att, bdb); return bdb; } @@ -3959,7 +3959,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s continue; } recentlyUsed(bdb2); - tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); + tdbb->bumpStats(PageStatType::FETCHES); cacheBuffer(att, bdb2); } else @@ -4914,7 +4914,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s // I won't wipe out the if() itself to allow my changes be verified easily by others if (true) { - tdbb->bumpStats(RuntimeStatistics::PAGE_WRITES); + tdbb->bumpStats(PageStatType::WRITES); // write out page to main database file, and to any // shadows, making a special case of the header page diff --git a/src/jrd/inf.cpp b/src/jrd/inf.cpp index b65ba73ef54..6e1966a7d45 100644 --- a/src/jrd/inf.cpp +++ b/src/jrd/inf.cpp @@ -125,20 +125,19 @@ namespace typedef HalfStaticArray CountsBuffer; - ULONG getCounts(thread_db* tdbb, RuntimeStatistics::StatType type, CountsBuffer& buffer) + ULONG getCounts(thread_db* tdbb, RecordStatType type, CountsBuffer& buffer) { - const Attachment* const attachment = tdbb->getAttachment(); - const RuntimeStatistics& stats = attachment->att_stats; + const auto attachment = tdbb->getAttachment(); UCHAR num_buffer[BUFFER_TINY]; buffer.clear(); FB_SIZE_T buffer_length = 0; - for (RuntimeStatistics::Iterator iter = stats.begin(); iter != stats.end(); ++iter) + for (auto iter(attachment->att_stats.getRelCounters()); iter; ++iter) { const USHORT relation_id = (*iter).getRelationId(); - const SINT64 n = (*iter).getCounter(type); + const SINT64 n = (*iter)[type]; if (n) { @@ -313,19 +312,19 @@ void INF_database_info(thread_db* tdbb, break; case isc_info_reads: - length = INF_convert(dbb->dbb_stats.getValue(RuntimeStatistics::PAGE_READS), buffer); + length = INF_convert(dbb->dbb_stats[PageStatType::READS], buffer); break; case isc_info_writes: - length = INF_convert(dbb->dbb_stats.getValue(RuntimeStatistics::PAGE_WRITES), buffer); + length = INF_convert(dbb->dbb_stats[PageStatType::WRITES], buffer); break; case isc_info_fetches: - length = INF_convert(dbb->dbb_stats.getValue(RuntimeStatistics::PAGE_FETCHES), buffer); + length = INF_convert(dbb->dbb_stats[PageStatType::FETCHES], buffer); break; case isc_info_marks: - length = INF_convert(dbb->dbb_stats.getValue(RuntimeStatistics::PAGE_MARKS), buffer); + length = INF_convert(dbb->dbb_stats[PageStatType::MARKS], buffer); break; case isc_info_page_size: @@ -407,42 +406,42 @@ void INF_database_info(thread_db* tdbb, break; case isc_info_read_seq_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_SEQ_READS, counts_buffer); + length = getCounts(tdbb, RecordStatType::SEQ_READS, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_read_idx_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_IDX_READS, counts_buffer); + length = getCounts(tdbb, RecordStatType::IDX_READS, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_update_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_UPDATES, counts_buffer); + length = getCounts(tdbb, RecordStatType::UPDATES, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_insert_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_INSERTS, counts_buffer); + length = getCounts(tdbb, RecordStatType::INSERTS, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_delete_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_DELETES, counts_buffer); + length = getCounts(tdbb, RecordStatType::DELETES, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_backout_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_BACKOUTS, counts_buffer); + length = getCounts(tdbb, RecordStatType::BACKOUTS, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_purge_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_PURGES, counts_buffer); + length = getCounts(tdbb, RecordStatType::PURGES, counts_buffer); buffer = counts_buffer.begin(); break; case isc_info_expunge_count: - length = getCounts(tdbb, RuntimeStatistics::RECORD_EXPUNGES, counts_buffer); + length = getCounts(tdbb, RecordStatType::EXPUNGES, counts_buffer); buffer = counts_buffer.begin(); break; diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index 9f2d9ade300..2e3644c89cc 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -612,25 +612,25 @@ class thread_db final : public Firebird::ThreadData tdbb_flags |= TDBB_sweeper; } - void bumpStats(const RuntimeStatistics::StatType index, SINT64 delta = 1) + void bumpStats(const PageStatType type, SINT64 delta = 1) { - reqStat->bumpValue(index, delta); - traStat->bumpValue(index, delta); - attStat->bumpValue(index, delta); + reqStat->bumpValue(type, delta); + traStat->bumpValue(type, delta); + attStat->bumpValue(type, delta); if ((tdbb_flags & TDBB_async) && !attachment) - dbbStat->bumpValue(index, delta); + dbbStat->bumpValue(type, delta); // else dbbStat is adjusted from attStat, see Attachment::mergeAsyncStats() } - void bumpRelStats(const RuntimeStatistics::StatType index, SLONG relation_id, SINT64 delta = 1) + void bumpStats(const RecordStatType type, SLONG relation_id, SINT64 delta = 1) { // We don't bump counters for dbbStat here, they're merged from attStats on demand - reqStat->bumpValue(index, delta); - traStat->bumpValue(index, delta); - attStat->bumpValue(index, delta); + reqStat->bumpValue(type, delta); + traStat->bumpValue(type, delta); + attStat->bumpValue(type, delta); const RuntimeStatistics* const dummyStat = RuntimeStatistics::getDummy(); @@ -643,13 +643,13 @@ class thread_db final : public Firebird::ThreadData // dummy object concurrently. if (reqStat != dummyStat) - reqStat->bumpRelValue(index, relation_id, delta); + reqStat->bumpValue(type, relation_id, delta); if (traStat != dummyStat) - traStat->bumpRelValue(index, relation_id, delta); + traStat->bumpValue(type, relation_id, delta); if (attStat != dummyStat) - attStat->bumpRelValue(index, relation_id, delta); + attStat->bumpValue(type, relation_id, delta); } ISC_STATUS getCancelState(ISC_STATUS* secondary = NULL); diff --git a/src/jrd/recsrc/SortedStream.cpp b/src/jrd/recsrc/SortedStream.cpp index 6c81be3598e..90a6e54bd8c 100644 --- a/src/jrd/recsrc/SortedStream.cpp +++ b/src/jrd/recsrc/SortedStream.cpp @@ -487,7 +487,7 @@ void SortedStream::mapData(thread_db* tdbb, Request* request, UCHAR* data) const if (!DPM_get(tdbb, &temp, LCK_read)) Arg::Gds(isc_no_cur_rec).raise(); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_RPT_READS, relation->rel_id); + tdbb->bumpStats(RecordStatType::RPT_READS, relation->rel_id); if (VIO_chase_record_version(tdbb, &temp, transaction, tdbb->getDefaultPool(), false, false)) { @@ -591,8 +591,7 @@ void SortedStream::mapData(thread_db* tdbb, Request* request, UCHAR* data) const // We have to find the original record version, sigh. // Scan version chain backwards until it's done. - RuntimeStatistics::Accumulator backversions(tdbb, relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); + RuntimeStatistics::Accumulator backversions(tdbb, relation, RecordStatType::BACK_READS); while (temp.rpb_transaction_nr != orgTraNum) { diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 518dd9648ae..1590c1c293e 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -4295,17 +4295,10 @@ void TraceSweepEvent::endSweepRelation(jrd_rel* relation) jrd_tra* tran = m_tdbb->getTransaction(); // don't report empty relation - if (m_base_stats.getValue(RuntimeStatistics::RECORD_SEQ_READS) == - tran->tra_stats.getValue(RuntimeStatistics::RECORD_SEQ_READS) && - - m_base_stats.getValue(RuntimeStatistics::RECORD_BACKOUTS) == - tran->tra_stats.getValue(RuntimeStatistics::RECORD_BACKOUTS) && - - m_base_stats.getValue(RuntimeStatistics::RECORD_PURGES) == - tran->tra_stats.getValue(RuntimeStatistics::RECORD_PURGES) && - - m_base_stats.getValue(RuntimeStatistics::RECORD_EXPUNGES) == - tran->tra_stats.getValue(RuntimeStatistics::RECORD_EXPUNGES) ) + if (m_base_stats[RecordStatType::SEQ_READS] == tran->tra_stats[RecordStatType::SEQ_READS] && + m_base_stats[RecordStatType::BACKOUTS] == tran->tra_stats[RecordStatType::BACKOUTS] && + m_base_stats[RecordStatType::PURGES] == tran->tra_stats[RecordStatType::PURGES] && + m_base_stats[RecordStatType::EXPUNGES] == tran->tra_stats[RecordStatType::EXPUNGES] ) { return; } diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 35207f95634..4632da2fd79 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -655,7 +655,7 @@ TraceRuntimeStats::TraceRuntimeStats(Attachment* att, RuntimeStatistics* baselin } } -SINT64 TraceRuntimeStats::m_dummy_counts[RuntimeStatistics::TOTAL_ITEMS] = {0}; +SINT64 TraceRuntimeStats::m_dummy_counts[RuntimeStatistics::GLOBAL_ITEMS] = {0}; /// TraceStatusVectorImpl diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index 608db59781a..f20cd8b0038 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -674,7 +674,7 @@ class TraceRuntimeStats Firebird::PerformanceInfo m_info; TraceCountsArray m_counts; Firebird::ObjectsArray m_tempNames; - static SINT64 m_dummy_counts[RuntimeStatistics::TOTAL_ITEMS]; // Zero-initialized array with zero counts + static SINT64 m_dummy_counts[RuntimeStatistics::GLOBAL_ITEMS]; // Zero-initialized array with zero counts }; diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 6c595ab9105..1e81339c90f 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -709,7 +709,7 @@ inline void check_gbak_cheating_delete(thread_db* tdbb, const jrd_rel* relation) inline int wait(thread_db* tdbb, jrd_tra* transaction, const record_param* rpb, bool probe) { if (!probe && transaction->getLockWait()) - tdbb->bumpRelStats(RuntimeStatistics::RECORD_WAITS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::WAITS, rpb->rpb_relation->rel_id); return TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, probe ? jrd_tra::tra_probe : jrd_tra::tra_wait); @@ -921,8 +921,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) // If there is an old version of the record, fetch it's data now. - RuntimeStatistics::Accumulator backversions(tdbb, relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); + RuntimeStatistics::Accumulator backversions(tdbb, relation, RecordStatType::BACK_READS); if (rpb->rpb_b_page) { @@ -1034,7 +1033,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) gcLockGuard.release(); delete_record(tdbb, rpb, 0, NULL); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_BACKOUTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::BACKOUTS, relation->rel_id); return; } @@ -1122,7 +1121,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) delete_record(tdbb, &temp, rpb->rpb_page, NULL); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_BACKOUTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::BACKOUTS, relation->rel_id); } @@ -1227,8 +1226,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, // satisfactory version is found or we run into a brick wall. Do any // garbage collection that seems appropriate. - RuntimeStatistics::Accumulator backversions(tdbb, relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); + RuntimeStatistics::Accumulator backversions(tdbb, relation, RecordStatType::BACK_READS); const bool skipLocked = rpb->rpb_stream_flags & RPB_s_skipLocked; @@ -1330,7 +1328,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, if (state == tra_active) { - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, relation->rel_id); // Cannot use Arg::Num here because transaction number is 64-bit unsigned integer ERR_post(Arg::Gds(isc_deadlock) << @@ -1849,7 +1847,7 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool) tail = unpack(rpb, tail_end - tail, tail); - RuntimeStatistics::Accumulator fragments(tdbb, relation, RuntimeStatistics::RECORD_FRAGMENT_READS); + RuntimeStatistics::Accumulator fragments(tdbb, relation, RecordStatType::FRAGMENT_READS); if (rpb->rpb_flags & rpb_incomplete) { @@ -2438,7 +2436,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if ((dbb->dbb_flags & DBB_gc_background) && !rpb->rpb_relation->isTemporary() && !backVersion) notify_garbage_collector(tdbb, rpb, transaction->tra_number); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_DELETES, relation->rel_id); + tdbb->bumpStats(RecordStatType::DELETES, relation->rel_id); return true; } @@ -2506,7 +2504,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if (transaction->tra_save_point && transaction->tra_save_point->isChanging()) verb_post(tdbb, transaction, rpb, 0); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_DELETES, relation->rel_id); + tdbb->bumpStats(RecordStatType::DELETES, relation->rel_id); // for an autocommit transaction, mark a commit as necessary @@ -2845,7 +2843,7 @@ void VIO_intermediate_gc(thread_db* tdbb, record_param* rpb, jrd_tra* transactio clearRecordStack(staying); clearRecordStack(going); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_IMGC, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::IMGC, rpb->rpb_relation->rel_id); } bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) @@ -3050,7 +3048,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo VIO_data(tdbb, rpb, pool); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_IDX_READS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::IDX_READS, rpb->rpb_relation->rel_id); return true; } @@ -3125,7 +3123,7 @@ bool VIO_get_current(thread_db* tdbb, if (!counted) { - tdbb->bumpRelStats(RuntimeStatistics::RECORD_IDX_READS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::IDX_READS, rpb->rpb_relation->rel_id); counted = true; } @@ -3409,7 +3407,7 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j if (transaction->tra_flags & TRA_system) { VIO_update_in_place(tdbb, transaction, org_rpb, new_rpb); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_UPDATES, relation->rel_id); + tdbb->bumpStats(RecordStatType::UPDATES, relation->rel_id); return true; } @@ -3825,7 +3823,7 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j verb_post(tdbb, transaction, org_rpb, org_rpb->rpb_undo); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_UPDATES, relation->rel_id); + tdbb->bumpStats(RecordStatType::UPDATES, relation->rel_id); return true; } @@ -3860,7 +3858,7 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j verb_post(tdbb, transaction, org_rpb, 0); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_UPDATES, relation->rel_id); + tdbb->bumpStats(RecordStatType::UPDATES, relation->rel_id); // for an autocommit transaction, mark a commit as necessary @@ -3969,7 +3967,7 @@ bool VIO_next_record(thread_db* tdbb, rpb->rpb_f_page, rpb->rpb_f_line); #endif - tdbb->bumpRelStats(RuntimeStatistics::RECORD_SEQ_READS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::SEQ_READS, rpb->rpb_relation->rel_id); return true; } @@ -4061,7 +4059,7 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction VIO_data(tdbb, rpb, tdbb->getDefaultPool()); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_RPT_READS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::RPT_READS, rpb->rpb_relation->rel_id); // If record is present, and the transaction is read committed, // make sure the record has not been updated. Also, punt after @@ -4076,7 +4074,7 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction // dimitr: reads using the undo log are also OK !(rpb->rpb_runtime_flags & RPB_undo_read)) { - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, rpb->rpb_relation->rel_id); // Cannot use Arg::Num here because transaction number is 64-bit unsigned integer ERR_post(Arg::Gds(isc_deadlock) << @@ -4723,7 +4721,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) verb_post(tdbb, transaction, rpb, 0); } - tdbb->bumpRelStats(RuntimeStatistics::RECORD_INSERTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::INSERTS, relation->rel_id); // for an autocommit transaction, mark a commit as necessary @@ -5023,7 +5021,7 @@ WriteLockResult VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* t if (transaction->tra_flags & TRA_autocommit) transaction->tra_flags |= TRA_perform_autocommit; - tdbb->bumpRelStats(RuntimeStatistics::RECORD_LOCKS, relation->rel_id); + tdbb->bumpStats(RecordStatType::LOCKS, relation->rel_id); // VIO_writelock Database* dbb = tdbb->getDatabase(); @@ -5374,8 +5372,7 @@ static UCHAR* delete_tail(thread_db* tdbb, rpb->rpb_f_page, rpb->rpb_f_line); #endif - RuntimeStatistics::Accumulator fragments(tdbb, rpb->rpb_relation, - RuntimeStatistics::RECORD_FRAGMENT_READS); + RuntimeStatistics::Accumulator fragments(tdbb, rpb->rpb_relation, RecordStatType::FRAGMENT_READS); while (rpb->rpb_flags & rpb_incomplete) { @@ -5519,7 +5516,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti RecordStack empty_staying; garbage_collect(tdbb, &temp, rpb->rpb_page, empty_staying); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_EXPUNGES, rpb->rpb_relation->rel_id); + tdbb->bumpStats(RecordStatType::EXPUNGES, rpb->rpb_relation->rel_id); } @@ -5558,8 +5555,7 @@ static void garbage_collect(thread_db* tdbb, record_param* rpb, ULONG prior_page rpb->rpb_f_page, rpb->rpb_f_line); #endif - RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); + RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, RecordStatType::BACK_READS); // Delete old versions fetching data for garbage collection. @@ -6147,8 +6143,7 @@ static void list_staying_fast(thread_db* tdbb, record_param* rpb, RecordStack& s (rpb->rpb_flags & ~(rpb_incomplete | rpb_not_packed))); Record* backout_rec = NULL; - RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); + RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, RecordStatType::BACK_READS); if (temp.rpb_flags & rpb_deleted) { @@ -6225,7 +6220,7 @@ static void list_staying_fast(thread_db* tdbb, record_param* rpb, RecordStack& s garbage_collect(tdbb, &temp2, temp.rpb_page, staying); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_PURGES, temp.rpb_relation->rel_id); + tdbb->bumpStats(RuntimeStatistics::RECORD_PURGES, temp.rpb_relation->rel_id); if (back_rpb && back_rpb->rpb_page == page && back_rpb->rpb_line == line) { @@ -6287,9 +6282,7 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin // significantly optimized in a case when VIO_data doesn't have to chase fragments. // I won't implement this now, because intermediate GC shall reduce likelihood // of encountering long version chains to almost zero. - RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, - RuntimeStatistics::RECORD_BACKVERSION_READS); - + RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, RecordStatType::BACK_READS); // Limit number of "restarts" if primary version constantly changed. Currently, // LS_ACTIVE_RPB is passed by VIO_intermediate_gc only and it is ok to return @@ -6638,7 +6631,7 @@ static PrepareResult prepare_update(thread_db* tdbb, jrd_tra* transaction, TraNu delete_record(tdbb, temp, 0, NULL); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, relation->rel_id); return PrepareResult::DELETED; } } @@ -6683,7 +6676,7 @@ static PrepareResult prepare_update(thread_db* tdbb, jrd_tra* transaction, TraNu if (writelock || skipLocked || (transaction->tra_flags & TRA_read_consistency)) { - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, relation->rel_id); return PrepareResult::DELETED; } @@ -6704,7 +6697,7 @@ static PrepareResult prepare_update(thread_db* tdbb, jrd_tra* transaction, TraNu delete_record(tdbb, temp, 0, NULL); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, relation->rel_id); return PrepareResult::CONFLICT; } @@ -6807,7 +6800,7 @@ static PrepareResult prepare_update(thread_db* tdbb, jrd_tra* transaction, TraNu // For SNAPSHOT mode transactions raise error early if (!(transaction->tra_flags & TRA_read_committed)) { - tdbb->bumpRelStats(RuntimeStatistics::RECORD_CONFLICTS, relation->rel_id); + tdbb->bumpStats(RecordStatType::CONFLICTS, relation->rel_id); if (skipLocked) return PrepareResult::SKIP_LOCKED; @@ -6996,7 +6989,7 @@ static void purge(thread_db* tdbb, record_param* rpb) staying.push(record); garbage_collect(tdbb, &temp, rpb->rpb_page, staying); - tdbb->bumpRelStats(RuntimeStatistics::RECORD_PURGES, relation->rel_id); + tdbb->bumpStats(RecordStatType::PURGES, relation->rel_id); return; // true; }