diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index 06601ffa6ef..9b6ae6fd37a 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -1364,6 +1364,9 @@ interface TraceTransaction : Versioned version: // 3.0.4 -> 3.0.5 int64 getInitialID(); int64 getPreviousID(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceParams : Versioned @@ -1379,6 +1382,9 @@ interface TraceStatement : Versioned { int64 getStmtID(); PerformanceInfo* getPerf(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceSQLStatement : TraceStatement @@ -1421,6 +1427,9 @@ version: // 4.0 -> 5.0 int64 getStmtID(); const string getPlan(); const string getExplainedPlan(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceFunction : Versioned @@ -1434,6 +1443,9 @@ version: // 4.0 -> 5.0 int64 getStmtID(); const string getPlan(); const string getExplainedPlan(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceTrigger : Versioned @@ -1456,6 +1468,9 @@ version: // 4.0 -> 5.0 int64 getStmtID(); const string getPlan(); const string getExplainedPlan(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceServiceConnection : TraceConnection @@ -1480,6 +1495,9 @@ interface TraceSweepInfo : Versioned int64 getOAT(); int64 getNext(); PerformanceInfo* getPerf(); + +version: // 5.0 -> 6.0 + PerformanceStats getPerfStats(); } interface TraceLogWriter : ReferenceCounted @@ -1876,3 +1894,48 @@ interface ProfilerStats : Versioned { uint64 getElapsedTicks(); } + +// Extendable replacement for struct PerformanceInfo + +interface PerformanceCounters : Versioned +{ + // Page-level performance counters (grouped per tablespace) + const uint PAGE_FETCHES = 0; + const uint PAGE_READS = 1; + const uint PAGE_MARKS = 2; + const uint PAGE_WRITES = 3; + + // Record-level performance counters (grouped per table) + const uint RECORD_SEQ_READS = 0; + const uint RECORD_IDX_READS = 1; + const uint RECORD_UPDATES = 2; + const uint RECORD_INSERTS = 3; + const uint RECORD_DELETES = 4; + const uint RECORD_BACKOUTS = 5; + const uint RECORD_PURGES = 6; + const uint RECORD_EXPUNGES = 7; + const uint RECORD_LOCKS = 8; + const uint RECORD_WAITS = 9; + const uint RECORD_CONFLICTS = 10; + const uint RECORD_BACK_READS = 11; + const uint RECORD_FRAGMENT_READS = 12; + const uint RECORD_RPT_READS = 13; + const uint RECORD_IMGC = 14; + + uint getObjectCount(); + uint getCountersCapacity(); + + uint getObjectId(uint index); + const string getObjectName(uint index); + const int64* getObjectCounters(uint index); +} + +interface PerformanceStats : Versioned +{ + uint64 getElapsedTime(); // in milliseconds + uint64 getFetchedRecords(); + + PerformanceCounters getPageCounters(); + PerformanceCounters getTableCounters(); +} + diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 43f3041054d..33e425251e7 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -143,6 +143,8 @@ namespace Firebird class IProfilerPlugin; class IProfilerSession; class IProfilerStats; + class IPerformanceCounters; + class IPerformanceStats; // Interfaces declarations @@ -5458,7 +5460,7 @@ namespace Firebird } }; -#define FIREBIRD_ITRACE_TRANSACTION_VERSION 3u +#define FIREBIRD_ITRACE_TRANSACTION_VERSION 4u class ITraceTransaction : public IVersioned { @@ -5472,6 +5474,7 @@ namespace Firebird PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceTransaction* self) CLOOP_NOEXCEPT; ISC_INT64 (CLOOP_CARG *getInitialID)(ITraceTransaction* self) CLOOP_NOEXCEPT; ISC_INT64 (CLOOP_CARG *getPreviousID)(ITraceTransaction* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceTransaction* self) CLOOP_NOEXCEPT; }; protected: @@ -5542,6 +5545,16 @@ namespace Firebird ISC_INT64 ret = static_cast(this->cloopVTable)->getPreviousID(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 4) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; #define FIREBIRD_ITRACE_PARAMS_VERSION 3u @@ -5596,7 +5609,7 @@ namespace Firebird } }; -#define FIREBIRD_ITRACE_STATEMENT_VERSION 2u +#define FIREBIRD_ITRACE_STATEMENT_VERSION 3u class ITraceStatement : public IVersioned { @@ -5605,6 +5618,7 @@ namespace Firebird { ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceStatement* self) CLOOP_NOEXCEPT; PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceStatement* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceStatement* self) CLOOP_NOEXCEPT; }; protected: @@ -5631,9 +5645,19 @@ namespace Firebird PerformanceInfo* ret = static_cast(this->cloopVTable)->getPerf(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 3) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; -#define FIREBIRD_ITRACE_SQLSTATEMENT_VERSION 3u +#define FIREBIRD_ITRACE_SQLSTATEMENT_VERSION 4u class ITraceSQLStatement : public ITraceStatement { @@ -5691,7 +5715,7 @@ namespace Firebird } }; -#define FIREBIRD_ITRACE_BLRSTATEMENT_VERSION 3u +#define FIREBIRD_ITRACE_BLRSTATEMENT_VERSION 4u class ITraceBLRStatement : public ITraceStatement { @@ -5823,7 +5847,7 @@ namespace Firebird } }; -#define FIREBIRD_ITRACE_PROCEDURE_VERSION 3u +#define FIREBIRD_ITRACE_PROCEDURE_VERSION 4u class ITraceProcedure : public IVersioned { @@ -5836,6 +5860,7 @@ namespace Firebird ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceProcedure* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getPlan)(ITraceProcedure* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getExplainedPlan)(ITraceProcedure* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceProcedure* self) CLOOP_NOEXCEPT; }; protected: @@ -5898,9 +5923,19 @@ namespace Firebird const char* ret = static_cast(this->cloopVTable)->getExplainedPlan(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 4) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; -#define FIREBIRD_ITRACE_FUNCTION_VERSION 3u +#define FIREBIRD_ITRACE_FUNCTION_VERSION 4u class ITraceFunction : public IVersioned { @@ -5914,6 +5949,7 @@ namespace Firebird ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceFunction* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getPlan)(ITraceFunction* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getExplainedPlan)(ITraceFunction* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceFunction* self) CLOOP_NOEXCEPT; }; protected: @@ -5982,9 +6018,19 @@ namespace Firebird const char* ret = static_cast(this->cloopVTable)->getExplainedPlan(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 4) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; -#define FIREBIRD_ITRACE_TRIGGER_VERSION 3u +#define FIREBIRD_ITRACE_TRIGGER_VERSION 4u class ITraceTrigger : public IVersioned { @@ -5999,6 +6045,7 @@ namespace Firebird ISC_INT64 (CLOOP_CARG *getStmtID)(ITraceTrigger* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getPlan)(ITraceTrigger* self) CLOOP_NOEXCEPT; const char* (CLOOP_CARG *getExplainedPlan)(ITraceTrigger* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceTrigger* self) CLOOP_NOEXCEPT; }; protected: @@ -6077,6 +6124,16 @@ namespace Firebird const char* ret = static_cast(this->cloopVTable)->getExplainedPlan(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 4) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; #define FIREBIRD_ITRACE_SERVICE_CONNECTION_VERSION 3u @@ -6174,7 +6231,7 @@ namespace Firebird } }; -#define FIREBIRD_ITRACE_SWEEP_INFO_VERSION 2u +#define FIREBIRD_ITRACE_SWEEP_INFO_VERSION 3u class ITraceSweepInfo : public IVersioned { @@ -6186,6 +6243,7 @@ namespace Firebird ISC_INT64 (CLOOP_CARG *getOAT)(ITraceSweepInfo* self) CLOOP_NOEXCEPT; ISC_INT64 (CLOOP_CARG *getNext)(ITraceSweepInfo* self) CLOOP_NOEXCEPT; PerformanceInfo* (CLOOP_CARG *getPerf)(ITraceSweepInfo* self) CLOOP_NOEXCEPT; + IPerformanceStats* (CLOOP_CARG *getPerfStats)(ITraceSweepInfo* self) CLOOP_NOEXCEPT; }; protected: @@ -6230,6 +6288,16 @@ namespace Firebird PerformanceInfo* ret = static_cast(this->cloopVTable)->getPerf(this); return ret; } + + IPerformanceStats* getPerfStats() + { + if (cloopVTable->version < 3) + { + return 0; + } + IPerformanceStats* ret = static_cast(this->cloopVTable)->getPerfStats(this); + return ret; + } }; #define FIREBIRD_ITRACE_LOG_WRITER_VERSION 4u @@ -7538,6 +7606,135 @@ namespace Firebird } }; +#define FIREBIRD_IPERFORMANCE_COUNTERS_VERSION 2u + + class IPerformanceCounters : public IVersioned + { + public: + struct VTable : public IVersioned::VTable + { + unsigned (CLOOP_CARG *getObjectCount)(IPerformanceCounters* self) CLOOP_NOEXCEPT; + unsigned (CLOOP_CARG *getCountersCapacity)(IPerformanceCounters* self) CLOOP_NOEXCEPT; + unsigned (CLOOP_CARG *getObjectId)(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT; + const char* (CLOOP_CARG *getObjectName)(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT; + const ISC_INT64* (CLOOP_CARG *getObjectCounters)(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT; + }; + + protected: + IPerformanceCounters(DoNotInherit) + : IVersioned(DoNotInherit()) + { + } + + ~IPerformanceCounters() + { + } + + public: + static CLOOP_CONSTEXPR unsigned VERSION = FIREBIRD_IPERFORMANCE_COUNTERS_VERSION; + + static CLOOP_CONSTEXPR unsigned PAGE_FETCHES = 0; + static CLOOP_CONSTEXPR unsigned PAGE_READS = 1; + static CLOOP_CONSTEXPR unsigned PAGE_MARKS = 2; + static CLOOP_CONSTEXPR unsigned PAGE_WRITES = 3; + static CLOOP_CONSTEXPR unsigned RECORD_SEQ_READS = 0; + static CLOOP_CONSTEXPR unsigned RECORD_IDX_READS = 1; + static CLOOP_CONSTEXPR unsigned RECORD_UPDATES = 2; + static CLOOP_CONSTEXPR unsigned RECORD_INSERTS = 3; + static CLOOP_CONSTEXPR unsigned RECORD_DELETES = 4; + static CLOOP_CONSTEXPR unsigned RECORD_BACKOUTS = 5; + static CLOOP_CONSTEXPR unsigned RECORD_PURGES = 6; + static CLOOP_CONSTEXPR unsigned RECORD_EXPUNGES = 7; + static CLOOP_CONSTEXPR unsigned RECORD_LOCKS = 8; + static CLOOP_CONSTEXPR unsigned RECORD_WAITS = 9; + static CLOOP_CONSTEXPR unsigned RECORD_CONFLICTS = 10; + static CLOOP_CONSTEXPR unsigned RECORD_BACK_READS = 11; + static CLOOP_CONSTEXPR unsigned RECORD_FRAGMENT_READS = 12; + static CLOOP_CONSTEXPR unsigned RECORD_RPT_READS = 13; + static CLOOP_CONSTEXPR unsigned RECORD_IMGC = 14; + + unsigned getObjectCount() + { + unsigned ret = static_cast(this->cloopVTable)->getObjectCount(this); + return ret; + } + + unsigned getCountersCapacity() + { + unsigned ret = static_cast(this->cloopVTable)->getCountersCapacity(this); + return ret; + } + + unsigned getObjectId(unsigned index) + { + unsigned ret = static_cast(this->cloopVTable)->getObjectId(this, index); + return ret; + } + + const char* getObjectName(unsigned index) + { + const char* ret = static_cast(this->cloopVTable)->getObjectName(this, index); + return ret; + } + + const ISC_INT64* getObjectCounters(unsigned index) + { + const ISC_INT64* ret = static_cast(this->cloopVTable)->getObjectCounters(this, index); + return ret; + } + }; + +#define FIREBIRD_IPERFORMANCE_STATS_VERSION 2u + + class IPerformanceStats : public IVersioned + { + public: + struct VTable : public IVersioned::VTable + { + ISC_UINT64 (CLOOP_CARG *getElapsedTime)(IPerformanceStats* self) CLOOP_NOEXCEPT; + ISC_UINT64 (CLOOP_CARG *getFetchedRecords)(IPerformanceStats* self) CLOOP_NOEXCEPT; + IPerformanceCounters* (CLOOP_CARG *getPageCounters)(IPerformanceStats* self) CLOOP_NOEXCEPT; + IPerformanceCounters* (CLOOP_CARG *getTableCounters)(IPerformanceStats* self) CLOOP_NOEXCEPT; + }; + + protected: + IPerformanceStats(DoNotInherit) + : IVersioned(DoNotInherit()) + { + } + + ~IPerformanceStats() + { + } + + public: + static CLOOP_CONSTEXPR unsigned VERSION = FIREBIRD_IPERFORMANCE_STATS_VERSION; + + ISC_UINT64 getElapsedTime() + { + ISC_UINT64 ret = static_cast(this->cloopVTable)->getElapsedTime(this); + return ret; + } + + ISC_UINT64 getFetchedRecords() + { + ISC_UINT64 ret = static_cast(this->cloopVTable)->getFetchedRecords(this); + return ret; + } + + IPerformanceCounters* getPageCounters() + { + IPerformanceCounters* ret = static_cast(this->cloopVTable)->getPageCounters(this); + return ret; + } + + IPerformanceCounters* getTableCounters() + { + IPerformanceCounters* ret = static_cast(this->cloopVTable)->getTableCounters(this); + return ret; + } + }; + // Interfaces implementations template @@ -17637,6 +17834,7 @@ namespace Firebird this->getPerf = &Name::cloopgetPerfDispatcher; this->getInitialID = &Name::cloopgetInitialIDDispatcher; this->getPreviousID = &Name::cloopgetPreviousIDDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -17733,6 +17931,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceTransaction* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -17755,6 +17966,7 @@ namespace Firebird virtual PerformanceInfo* getPerf() = 0; virtual ISC_INT64 getInitialID() = 0; virtual ISC_INT64 getPreviousID() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -17854,6 +18066,7 @@ namespace Firebird this->version = Base::VERSION; this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPerf = &Name::cloopgetPerfDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -17885,6 +18098,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceStatement* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -17902,6 +18128,7 @@ namespace Firebird virtual ISC_INT64 getStmtID() = 0; virtual PerformanceInfo* getPerf() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -17919,6 +18146,7 @@ namespace Firebird this->version = Base::VERSION; this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPerf = &Name::cloopgetPerfDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; this->getText = &Name::cloopgetTextDispatcher; this->getPlan = &Name::cloopgetPlanDispatcher; this->getInputs = &Name::cloopgetInputsDispatcher; @@ -18020,6 +18248,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceStatement* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > > > @@ -18057,6 +18298,7 @@ namespace Firebird this->version = Base::VERSION; this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPerf = &Name::cloopgetPerfDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; this->getData = &Name::cloopgetDataDispatcher; this->getDataLength = &Name::cloopgetDataLengthDispatcher; this->getText = &Name::cloopgetTextDispatcher; @@ -18130,6 +18372,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceStatement* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > > > @@ -18329,6 +18584,7 @@ namespace Firebird this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPlan = &Name::cloopgetPlanDispatcher; this->getExplainedPlan = &Name::cloopgetExplainedPlanDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -18412,6 +18668,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceProcedure* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -18433,6 +18702,7 @@ namespace Firebird virtual ISC_INT64 getStmtID() = 0; virtual const char* getPlan() = 0; virtual const char* getExplainedPlan() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -18455,6 +18725,7 @@ namespace Firebird this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPlan = &Name::cloopgetPlanDispatcher; this->getExplainedPlan = &Name::cloopgetExplainedPlanDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -18551,6 +18822,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceFunction* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -18573,6 +18857,7 @@ namespace Firebird virtual ISC_INT64 getStmtID() = 0; virtual const char* getPlan() = 0; virtual const char* getExplainedPlan() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -18596,6 +18881,7 @@ namespace Firebird this->getStmtID = &Name::cloopgetStmtIDDispatcher; this->getPlan = &Name::cloopgetPlanDispatcher; this->getExplainedPlan = &Name::cloopgetExplainedPlanDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -18705,6 +18991,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceTrigger* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -18728,6 +19027,7 @@ namespace Firebird virtual ISC_INT64 getStmtID() = 0; virtual const char* getPlan() = 0; virtual const char* getExplainedPlan() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -19049,6 +19349,7 @@ namespace Firebird this->getOAT = &Name::cloopgetOATDispatcher; this->getNext = &Name::cloopgetNextDispatcher; this->getPerf = &Name::cloopgetPerfDispatcher; + this->getPerfStats = &Name::cloopgetPerfStatsDispatcher; } } vTable; @@ -19119,6 +19420,19 @@ namespace Firebird return static_cast(0); } } + + static IPerformanceStats* CLOOP_CARG cloopgetPerfStatsDispatcher(ITraceSweepInfo* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPerfStats(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } }; template > > @@ -19139,6 +19453,7 @@ namespace Firebird virtual ISC_INT64 getOAT() = 0; virtual ISC_INT64 getNext() = 0; virtual PerformanceInfo* getPerf() = 0; + virtual IPerformanceStats* getPerfStats() = 0; }; template @@ -21698,6 +22013,211 @@ namespace Firebird virtual ISC_UINT64 getElapsedTicks() = 0; }; + + template + class IPerformanceCountersBaseImpl : public Base + { + public: + typedef IPerformanceCounters Declaration; + + IPerformanceCountersBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->getObjectCount = &Name::cloopgetObjectCountDispatcher; + this->getCountersCapacity = &Name::cloopgetCountersCapacityDispatcher; + this->getObjectId = &Name::cloopgetObjectIdDispatcher; + this->getObjectName = &Name::cloopgetObjectNameDispatcher; + this->getObjectCounters = &Name::cloopgetObjectCountersDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static unsigned CLOOP_CARG cloopgetObjectCountDispatcher(IPerformanceCounters* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getObjectCount(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static unsigned CLOOP_CARG cloopgetCountersCapacityDispatcher(IPerformanceCounters* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getCountersCapacity(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static unsigned CLOOP_CARG cloopgetObjectIdDispatcher(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getObjectId(index); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static const char* CLOOP_CARG cloopgetObjectNameDispatcher(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getObjectName(index); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static const ISC_INT64* CLOOP_CARG cloopgetObjectCountersDispatcher(IPerformanceCounters* self, unsigned index) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getObjectCounters(index); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + }; + + template > > + class IPerformanceCountersImpl : public IPerformanceCountersBaseImpl + { + protected: + IPerformanceCountersImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IPerformanceCountersImpl() + { + } + + virtual unsigned getObjectCount() = 0; + virtual unsigned getCountersCapacity() = 0; + virtual unsigned getObjectId(unsigned index) = 0; + virtual const char* getObjectName(unsigned index) = 0; + virtual const ISC_INT64* getObjectCounters(unsigned index) = 0; + }; + + template + class IPerformanceStatsBaseImpl : public Base + { + public: + typedef IPerformanceStats Declaration; + + IPerformanceStatsBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->getElapsedTime = &Name::cloopgetElapsedTimeDispatcher; + this->getFetchedRecords = &Name::cloopgetFetchedRecordsDispatcher; + this->getPageCounters = &Name::cloopgetPageCountersDispatcher; + this->getTableCounters = &Name::cloopgetTableCountersDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static ISC_UINT64 CLOOP_CARG cloopgetElapsedTimeDispatcher(IPerformanceStats* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getElapsedTime(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static ISC_UINT64 CLOOP_CARG cloopgetFetchedRecordsDispatcher(IPerformanceStats* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getFetchedRecords(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static IPerformanceCounters* CLOOP_CARG cloopgetPageCountersDispatcher(IPerformanceStats* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getPageCounters(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static IPerformanceCounters* CLOOP_CARG cloopgetTableCountersDispatcher(IPerformanceStats* self) CLOOP_NOEXCEPT + { + try + { + return static_cast(self)->Name::getTableCounters(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + }; + + template > > + class IPerformanceStatsImpl : public IPerformanceStatsBaseImpl + { + protected: + IPerformanceStatsImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IPerformanceStatsImpl() + { + } + + virtual ISC_UINT64 getElapsedTime() = 0; + virtual ISC_UINT64 getFetchedRecords() = 0; + virtual IPerformanceCounters* getPageCounters() = 0; + virtual IPerformanceCounters* getTableCounters() = 0; + }; }; diff --git a/src/include/gen/Firebird.pas b/src/include/gen/Firebird.pas index 4fdd5a676e3..f03e9b8efc2 100644 --- a/src/include/gen/Firebird.pas +++ b/src/include/gen/Firebird.pas @@ -114,6 +114,8 @@ IReplicatedSession = class; IProfilerPlugin = class; IProfilerSession = class; IProfilerStats = class; + IPerformanceCounters = class; + IPerformanceStats = class; FbException = class(Exception) public @@ -611,11 +613,13 @@ ISC_TIMESTAMP_TZ_EX = record ITraceTransaction_getPerfPtr = function(this: ITraceTransaction): PerformanceInfoPtr; cdecl; ITraceTransaction_getInitialIDPtr = function(this: ITraceTransaction): Int64; cdecl; ITraceTransaction_getPreviousIDPtr = function(this: ITraceTransaction): Int64; cdecl; + ITraceTransaction_getPerfStatsPtr = function(this: ITraceTransaction): IPerformanceStats; cdecl; ITraceParams_getCountPtr = function(this: ITraceParams): Cardinal; cdecl; ITraceParams_getParamPtr = function(this: ITraceParams; idx: Cardinal): paramdscPtr; cdecl; ITraceParams_getTextUTF8Ptr = function(this: ITraceParams; status: IStatus; idx: Cardinal): PAnsiChar; cdecl; ITraceStatement_getStmtIDPtr = function(this: ITraceStatement): Int64; cdecl; ITraceStatement_getPerfPtr = function(this: ITraceStatement): PerformanceInfoPtr; cdecl; + ITraceStatement_getPerfStatsPtr = function(this: ITraceStatement): IPerformanceStats; cdecl; ITraceSQLStatement_getTextPtr = function(this: ITraceSQLStatement): PAnsiChar; cdecl; ITraceSQLStatement_getPlanPtr = function(this: ITraceSQLStatement): PAnsiChar; cdecl; ITraceSQLStatement_getInputsPtr = function(this: ITraceSQLStatement): ITraceParams; cdecl; @@ -636,6 +640,7 @@ ISC_TIMESTAMP_TZ_EX = record ITraceProcedure_getStmtIDPtr = function(this: ITraceProcedure): Int64; cdecl; ITraceProcedure_getPlanPtr = function(this: ITraceProcedure): PAnsiChar; cdecl; ITraceProcedure_getExplainedPlanPtr = function(this: ITraceProcedure): PAnsiChar; cdecl; + ITraceProcedure_getPerfStatsPtr = function(this: ITraceProcedure): IPerformanceStats; cdecl; ITraceFunction_getFuncNamePtr = function(this: ITraceFunction): PAnsiChar; cdecl; ITraceFunction_getInputsPtr = function(this: ITraceFunction): ITraceParams; cdecl; ITraceFunction_getResultPtr = function(this: ITraceFunction): ITraceParams; cdecl; @@ -643,6 +648,7 @@ ISC_TIMESTAMP_TZ_EX = record ITraceFunction_getStmtIDPtr = function(this: ITraceFunction): Int64; cdecl; ITraceFunction_getPlanPtr = function(this: ITraceFunction): PAnsiChar; cdecl; ITraceFunction_getExplainedPlanPtr = function(this: ITraceFunction): PAnsiChar; cdecl; + ITraceFunction_getPerfStatsPtr = function(this: ITraceFunction): IPerformanceStats; cdecl; ITraceTrigger_getTriggerNamePtr = function(this: ITraceTrigger): PAnsiChar; cdecl; ITraceTrigger_getRelationNamePtr = function(this: ITraceTrigger): PAnsiChar; cdecl; ITraceTrigger_getActionPtr = function(this: ITraceTrigger): Integer; cdecl; @@ -651,6 +657,7 @@ ISC_TIMESTAMP_TZ_EX = record ITraceTrigger_getStmtIDPtr = function(this: ITraceTrigger): Int64; cdecl; ITraceTrigger_getPlanPtr = function(this: ITraceTrigger): PAnsiChar; cdecl; ITraceTrigger_getExplainedPlanPtr = function(this: ITraceTrigger): PAnsiChar; cdecl; + ITraceTrigger_getPerfStatsPtr = function(this: ITraceTrigger): IPerformanceStats; cdecl; ITraceServiceConnection_getServiceIDPtr = function(this: ITraceServiceConnection): Pointer; cdecl; ITraceServiceConnection_getServiceMgrPtr = function(this: ITraceServiceConnection): PAnsiChar; cdecl; ITraceServiceConnection_getServiceNamePtr = function(this: ITraceServiceConnection): PAnsiChar; cdecl; @@ -663,6 +670,7 @@ ISC_TIMESTAMP_TZ_EX = record ITraceSweepInfo_getOATPtr = function(this: ITraceSweepInfo): Int64; cdecl; ITraceSweepInfo_getNextPtr = function(this: ITraceSweepInfo): Int64; cdecl; ITraceSweepInfo_getPerfPtr = function(this: ITraceSweepInfo): PerformanceInfoPtr; cdecl; + ITraceSweepInfo_getPerfStatsPtr = function(this: ITraceSweepInfo): IPerformanceStats; cdecl; ITraceLogWriter_writePtr = function(this: ITraceLogWriter; buf: Pointer; size: Cardinal): Cardinal; cdecl; ITraceLogWriter_write_sPtr = function(this: ITraceLogWriter; status: IStatus; buf: Pointer; size: Cardinal): Cardinal; cdecl; ITraceInitInfo_getConfigTextPtr = function(this: ITraceInitInfo): PAnsiChar; cdecl; @@ -770,6 +778,15 @@ ISC_TIMESTAMP_TZ_EX = record IProfilerSession_afterRecordSourceGetRecordPtr = procedure(this: IProfilerSession; statementId: Int64; requestId: Int64; cursorId: Cardinal; recSourceId: Cardinal; stats: IProfilerStats); cdecl; IProfilerSession_defineStatement2Ptr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; schemaName: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar); cdecl; IProfilerStats_getElapsedTicksPtr = function(this: IProfilerStats): QWord; cdecl; + IPerformanceCounters_getObjectCountPtr = function(this: IPerformanceCounters): Cardinal; cdecl; + IPerformanceCounters_getCountersCapacityPtr = function(this: IPerformanceCounters): Cardinal; cdecl; + IPerformanceCounters_getObjectIdPtr = function(this: IPerformanceCounters; index: Cardinal): Cardinal; cdecl; + IPerformanceCounters_getObjectNamePtr = function(this: IPerformanceCounters; index: Cardinal): PAnsiChar; cdecl; + IPerformanceCounters_getObjectCountersPtr = function(this: IPerformanceCounters; index: Cardinal): Int64Ptr; cdecl; + IPerformanceStats_getElapsedTimePtr = function(this: IPerformanceStats): QWord; cdecl; + IPerformanceStats_getFetchedRecordsPtr = function(this: IPerformanceStats): QWord; cdecl; + IPerformanceStats_getPageCountersPtr = function(this: IPerformanceStats): IPerformanceCounters; cdecl; + IPerformanceStats_getTableCountersPtr = function(this: IPerformanceStats): IPerformanceCounters; cdecl; VersionedVTable = class version: NativeInt; @@ -3052,10 +3069,11 @@ TraceTransactionVTable = class(VersionedVTable) getPerf: ITraceTransaction_getPerfPtr; getInitialID: ITraceTransaction_getInitialIDPtr; getPreviousID: ITraceTransaction_getPreviousIDPtr; + getPerfStats: ITraceTransaction_getPerfStatsPtr; end; ITraceTransaction = class(IVersioned) - const VERSION = 3; + const VERSION = 4; const ISOLATION_CONSISTENCY = Cardinal(1); const ISOLATION_CONCURRENCY = Cardinal(2); const ISOLATION_READ_COMMITTED_RECVER = Cardinal(3); @@ -3069,6 +3087,7 @@ ITraceTransaction = class(IVersioned) function getPerf(): PerformanceInfoPtr; function getInitialID(): Int64; function getPreviousID(): Int64; + function getPerfStats(): IPerformanceStats; end; ITraceTransactionImpl = class(ITraceTransaction) @@ -3081,6 +3100,7 @@ ITraceTransactionImpl = class(ITraceTransaction) function getPerf(): PerformanceInfoPtr; virtual; abstract; function getInitialID(): Int64; virtual; abstract; function getPreviousID(): Int64; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceParamsVTable = class(VersionedVTable) @@ -3108,13 +3128,15 @@ ITraceParamsImpl = class(ITraceParams) TraceStatementVTable = class(VersionedVTable) getStmtID: ITraceStatement_getStmtIDPtr; getPerf: ITraceStatement_getPerfPtr; + getPerfStats: ITraceStatement_getPerfStatsPtr; end; ITraceStatement = class(IVersioned) - const VERSION = 2; + const VERSION = 3; function getStmtID(): Int64; function getPerf(): PerformanceInfoPtr; + function getPerfStats(): IPerformanceStats; end; ITraceStatementImpl = class(ITraceStatement) @@ -3122,6 +3144,7 @@ ITraceStatementImpl = class(ITraceStatement) function getStmtID(): Int64; virtual; abstract; function getPerf(): PerformanceInfoPtr; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceSQLStatementVTable = class(TraceStatementVTable) @@ -3133,7 +3156,7 @@ TraceSQLStatementVTable = class(TraceStatementVTable) end; ITraceSQLStatement = class(ITraceStatement) - const VERSION = 3; + const VERSION = 4; function getText(): PAnsiChar; function getPlan(): PAnsiChar; @@ -3147,6 +3170,7 @@ ITraceSQLStatementImpl = class(ITraceSQLStatement) function getStmtID(): Int64; virtual; abstract; function getPerf(): PerformanceInfoPtr; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; function getText(): PAnsiChar; virtual; abstract; function getPlan(): PAnsiChar; virtual; abstract; function getInputs(): ITraceParams; virtual; abstract; @@ -3161,7 +3185,7 @@ TraceBLRStatementVTable = class(TraceStatementVTable) end; ITraceBLRStatement = class(ITraceStatement) - const VERSION = 3; + const VERSION = 4; function getData(): BytePtr; function getDataLength(): Cardinal; @@ -3173,6 +3197,7 @@ ITraceBLRStatementImpl = class(ITraceBLRStatement) function getStmtID(): Int64; virtual; abstract; function getPerf(): PerformanceInfoPtr; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; function getData(): BytePtr; virtual; abstract; function getDataLength(): Cardinal; virtual; abstract; function getText(): PAnsiChar; virtual; abstract; @@ -3229,10 +3254,11 @@ TraceProcedureVTable = class(VersionedVTable) getStmtID: ITraceProcedure_getStmtIDPtr; getPlan: ITraceProcedure_getPlanPtr; getExplainedPlan: ITraceProcedure_getExplainedPlanPtr; + getPerfStats: ITraceProcedure_getPerfStatsPtr; end; ITraceProcedure = class(IVersioned) - const VERSION = 3; + const VERSION = 4; function getProcName(): PAnsiChar; function getInputs(): ITraceParams; @@ -3240,6 +3266,7 @@ ITraceProcedure = class(IVersioned) function getStmtID(): Int64; function getPlan(): PAnsiChar; function getExplainedPlan(): PAnsiChar; + function getPerfStats(): IPerformanceStats; end; ITraceProcedureImpl = class(ITraceProcedure) @@ -3251,6 +3278,7 @@ ITraceProcedureImpl = class(ITraceProcedure) function getStmtID(): Int64; virtual; abstract; function getPlan(): PAnsiChar; virtual; abstract; function getExplainedPlan(): PAnsiChar; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceFunctionVTable = class(VersionedVTable) @@ -3261,10 +3289,11 @@ TraceFunctionVTable = class(VersionedVTable) getStmtID: ITraceFunction_getStmtIDPtr; getPlan: ITraceFunction_getPlanPtr; getExplainedPlan: ITraceFunction_getExplainedPlanPtr; + getPerfStats: ITraceFunction_getPerfStatsPtr; end; ITraceFunction = class(IVersioned) - const VERSION = 3; + const VERSION = 4; function getFuncName(): PAnsiChar; function getInputs(): ITraceParams; @@ -3273,6 +3302,7 @@ ITraceFunction = class(IVersioned) function getStmtID(): Int64; function getPlan(): PAnsiChar; function getExplainedPlan(): PAnsiChar; + function getPerfStats(): IPerformanceStats; end; ITraceFunctionImpl = class(ITraceFunction) @@ -3285,6 +3315,7 @@ ITraceFunctionImpl = class(ITraceFunction) function getStmtID(): Int64; virtual; abstract; function getPlan(): PAnsiChar; virtual; abstract; function getExplainedPlan(): PAnsiChar; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceTriggerVTable = class(VersionedVTable) @@ -3296,10 +3327,11 @@ TraceTriggerVTable = class(VersionedVTable) getStmtID: ITraceTrigger_getStmtIDPtr; getPlan: ITraceTrigger_getPlanPtr; getExplainedPlan: ITraceTrigger_getExplainedPlanPtr; + getPerfStats: ITraceTrigger_getPerfStatsPtr; end; ITraceTrigger = class(IVersioned) - const VERSION = 3; + const VERSION = 4; const TYPE_ALL = Cardinal(0); const TYPE_BEFORE = Cardinal(1); const TYPE_AFTER = Cardinal(2); @@ -3312,6 +3344,7 @@ ITraceTrigger = class(IVersioned) function getStmtID(): Int64; function getPlan(): PAnsiChar; function getExplainedPlan(): PAnsiChar; + function getPerfStats(): IPerformanceStats; end; ITraceTriggerImpl = class(ITraceTrigger) @@ -3325,6 +3358,7 @@ ITraceTriggerImpl = class(ITraceTrigger) function getStmtID(): Int64; virtual; abstract; function getPlan(): PAnsiChar; virtual; abstract; function getExplainedPlan(): PAnsiChar; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceServiceConnectionVTable = class(TraceConnectionVTable) @@ -3389,16 +3423,18 @@ TraceSweepInfoVTable = class(VersionedVTable) getOAT: ITraceSweepInfo_getOATPtr; getNext: ITraceSweepInfo_getNextPtr; getPerf: ITraceSweepInfo_getPerfPtr; + getPerfStats: ITraceSweepInfo_getPerfStatsPtr; end; ITraceSweepInfo = class(IVersioned) - const VERSION = 2; + const VERSION = 3; function getOIT(): Int64; function getOST(): Int64; function getOAT(): Int64; function getNext(): Int64; function getPerf(): PerformanceInfoPtr; + function getPerfStats(): IPerformanceStats; end; ITraceSweepInfoImpl = class(ITraceSweepInfo) @@ -3409,6 +3445,7 @@ ITraceSweepInfoImpl = class(ITraceSweepInfo) function getOAT(): Int64; virtual; abstract; function getNext(): Int64; virtual; abstract; function getPerf(): PerformanceInfoPtr; virtual; abstract; + function getPerfStats(): IPerformanceStats; virtual; abstract; end; TraceLogWriterVTable = class(ReferenceCountedVTable) @@ -4025,6 +4062,78 @@ IProfilerStatsImpl = class(IProfilerStats) function getElapsedTicks(): QWord; virtual; abstract; end; + PerformanceCountersVTable = class(VersionedVTable) + getObjectCount: IPerformanceCounters_getObjectCountPtr; + getCountersCapacity: IPerformanceCounters_getCountersCapacityPtr; + getObjectId: IPerformanceCounters_getObjectIdPtr; + getObjectName: IPerformanceCounters_getObjectNamePtr; + getObjectCounters: IPerformanceCounters_getObjectCountersPtr; + end; + + IPerformanceCounters = class(IVersioned) + const VERSION = 2; + const PAGE_FETCHES = Cardinal(0); + const PAGE_READS = Cardinal(1); + const PAGE_MARKS = Cardinal(2); + const PAGE_WRITES = Cardinal(3); + const RECORD_SEQ_READS = Cardinal(0); + const RECORD_IDX_READS = Cardinal(1); + const RECORD_UPDATES = Cardinal(2); + const RECORD_INSERTS = Cardinal(3); + const RECORD_DELETES = Cardinal(4); + const RECORD_BACKOUTS = Cardinal(5); + const RECORD_PURGES = Cardinal(6); + const RECORD_EXPUNGES = Cardinal(7); + const RECORD_LOCKS = Cardinal(8); + const RECORD_WAITS = Cardinal(9); + const RECORD_CONFLICTS = Cardinal(10); + const RECORD_BACK_READS = Cardinal(11); + const RECORD_FRAGMENT_READS = Cardinal(12); + const RECORD_RPT_READS = Cardinal(13); + const RECORD_IMGC = Cardinal(14); + + function getObjectCount(): Cardinal; + function getCountersCapacity(): Cardinal; + function getObjectId(index: Cardinal): Cardinal; + function getObjectName(index: Cardinal): PAnsiChar; + function getObjectCounters(index: Cardinal): Int64Ptr; + end; + + IPerformanceCountersImpl = class(IPerformanceCounters) + constructor create; + + function getObjectCount(): Cardinal; virtual; abstract; + function getCountersCapacity(): Cardinal; virtual; abstract; + function getObjectId(index: Cardinal): Cardinal; virtual; abstract; + function getObjectName(index: Cardinal): PAnsiChar; virtual; abstract; + function getObjectCounters(index: Cardinal): Int64Ptr; virtual; abstract; + end; + + PerformanceStatsVTable = class(VersionedVTable) + getElapsedTime: IPerformanceStats_getElapsedTimePtr; + getFetchedRecords: IPerformanceStats_getFetchedRecordsPtr; + getPageCounters: IPerformanceStats_getPageCountersPtr; + getTableCounters: IPerformanceStats_getTableCountersPtr; + end; + + IPerformanceStats = class(IVersioned) + const VERSION = 2; + + function getElapsedTime(): QWord; + function getFetchedRecords(): QWord; + function getPageCounters(): IPerformanceCounters; + function getTableCounters(): IPerformanceCounters; + end; + + IPerformanceStatsImpl = class(IPerformanceStats) + constructor create; + + function getElapsedTime(): QWord; virtual; abstract; + function getFetchedRecords(): QWord; virtual; abstract; + function getPageCounters(): IPerformanceCounters; virtual; abstract; + function getTableCounters(): IPerformanceCounters; virtual; abstract; + end; + {$IFNDEF NO_FBCLIENT} function fb_get_master_interface : IMaster; cdecl; external 'fbclient'; {$ENDIF} @@ -9100,6 +9209,16 @@ function ITraceTransaction.getPreviousID(): Int64; end; end; +function ITraceTransaction.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 4) then begin + Result := nil; + end + else begin + Result := TraceTransactionVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceParams.getCount(): Cardinal; begin Result := TraceParamsVTable(vTable).getCount(Self); @@ -9132,6 +9251,16 @@ function ITraceStatement.getPerf(): PerformanceInfoPtr; Result := TraceStatementVTable(vTable).getPerf(Self); end; +function ITraceStatement.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 3) then begin + Result := nil; + end + else begin + Result := TraceStatementVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceSQLStatement.getText(): PAnsiChar; begin Result := TraceSQLStatementVTable(vTable).getText(Self); @@ -9247,6 +9376,16 @@ function ITraceProcedure.getExplainedPlan(): PAnsiChar; end; end; +function ITraceProcedure.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 4) then begin + Result := nil; + end + else begin + Result := TraceProcedureVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceFunction.getFuncName(): PAnsiChar; begin Result := TraceFunctionVTable(vTable).getFuncName(Self); @@ -9297,6 +9436,16 @@ function ITraceFunction.getExplainedPlan(): PAnsiChar; end; end; +function ITraceFunction.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 4) then begin + Result := nil; + end + else begin + Result := TraceFunctionVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceTrigger.getTriggerName(): PAnsiChar; begin Result := TraceTriggerVTable(vTable).getTriggerName(Self); @@ -9352,6 +9501,16 @@ function ITraceTrigger.getExplainedPlan(): PAnsiChar; end; end; +function ITraceTrigger.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 4) then begin + Result := nil; + end + else begin + Result := TraceTriggerVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceServiceConnection.getServiceID(): Pointer; begin Result := TraceServiceConnectionVTable(vTable).getServiceID(Self); @@ -9412,6 +9571,16 @@ function ITraceSweepInfo.getPerf(): PerformanceInfoPtr; Result := TraceSweepInfoVTable(vTable).getPerf(Self); end; +function ITraceSweepInfo.getPerfStats(): IPerformanceStats; +begin + if (vTable.version < 3) then begin + Result := nil; + end + else begin + Result := TraceSweepInfoVTable(vTable).getPerfStats(Self); + end; +end; + function ITraceLogWriter.write(buf: Pointer; size: Cardinal): Cardinal; begin Result := TraceLogWriterVTable(vTable).write(Self, buf, size); @@ -10049,6 +10218,51 @@ function IProfilerStats.getElapsedTicks(): QWord; Result := ProfilerStatsVTable(vTable).getElapsedTicks(Self); end; +function IPerformanceCounters.getObjectCount(): Cardinal; +begin + Result := PerformanceCountersVTable(vTable).getObjectCount(Self); +end; + +function IPerformanceCounters.getCountersCapacity(): Cardinal; +begin + Result := PerformanceCountersVTable(vTable).getCountersCapacity(Self); +end; + +function IPerformanceCounters.getObjectId(index: Cardinal): Cardinal; +begin + Result := PerformanceCountersVTable(vTable).getObjectId(Self, index); +end; + +function IPerformanceCounters.getObjectName(index: Cardinal): PAnsiChar; +begin + Result := PerformanceCountersVTable(vTable).getObjectName(Self, index); +end; + +function IPerformanceCounters.getObjectCounters(index: Cardinal): Int64Ptr; +begin + Result := PerformanceCountersVTable(vTable).getObjectCounters(Self, index); +end; + +function IPerformanceStats.getElapsedTime(): QWord; +begin + Result := PerformanceStatsVTable(vTable).getElapsedTime(Self); +end; + +function IPerformanceStats.getFetchedRecords(): QWord; +begin + Result := PerformanceStatsVTable(vTable).getFetchedRecords(Self); +end; + +function IPerformanceStats.getPageCounters(): IPerformanceCounters; +begin + Result := PerformanceStatsVTable(vTable).getPageCounters(Self); +end; + +function IPerformanceStats.getTableCounters(): IPerformanceCounters; +begin + Result := PerformanceStatsVTable(vTable).getTableCounters(Self); +end; + var IVersionedImpl_vTable: VersionedVTable; @@ -15428,6 +15642,16 @@ function ITraceTransactionImpl_getPreviousIDDispatcher(this: ITraceTransaction): end end; +function ITraceTransactionImpl_getPerfStatsDispatcher(this: ITraceTransaction): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceTransactionImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceTransactionImpl_vTable: TraceTransactionVTable; @@ -15494,6 +15718,16 @@ function ITraceStatementImpl_getPerfDispatcher(this: ITraceStatement): Performan end end; +function ITraceStatementImpl_getPerfStatsDispatcher(this: ITraceStatement): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceStatementImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceStatementImpl_vTable: TraceStatementVTable; @@ -15522,6 +15756,16 @@ function ITraceSQLStatementImpl_getPerfDispatcher(this: ITraceSQLStatement): Per end end; +function ITraceSQLStatementImpl_getPerfStatsDispatcher(this: ITraceSQLStatement): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceSQLStatementImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + function ITraceSQLStatementImpl_getTextDispatcher(this: ITraceSQLStatement): PAnsiChar; cdecl; begin Result := nil; @@ -15600,6 +15844,16 @@ function ITraceBLRStatementImpl_getPerfDispatcher(this: ITraceBLRStatement): Per end end; +function ITraceBLRStatementImpl_getPerfStatsDispatcher(this: ITraceBLRStatement): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceBLRStatementImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + function ITraceBLRStatementImpl_getDataDispatcher(this: ITraceBLRStatement): BytePtr; cdecl; begin Result := nil; @@ -15774,6 +16028,16 @@ function ITraceProcedureImpl_getExplainedPlanDispatcher(this: ITraceProcedure): end end; +function ITraceProcedureImpl_getPerfStatsDispatcher(this: ITraceProcedure): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceProcedureImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceProcedureImpl_vTable: TraceProcedureVTable; @@ -15852,6 +16116,16 @@ function ITraceFunctionImpl_getExplainedPlanDispatcher(this: ITraceFunction): PA end end; +function ITraceFunctionImpl_getPerfStatsDispatcher(this: ITraceFunction): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceFunctionImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceFunctionImpl_vTable: TraceFunctionVTable; @@ -15940,6 +16214,16 @@ function ITraceTriggerImpl_getExplainedPlanDispatcher(this: ITraceTrigger): PAns end end; +function ITraceTriggerImpl_getPerfStatsDispatcher(this: ITraceTrigger): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceTriggerImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceTriggerImpl_vTable: TraceTriggerVTable; @@ -16174,6 +16458,16 @@ function ITraceSweepInfoImpl_getPerfDispatcher(this: ITraceSweepInfo): Performan end end; +function ITraceSweepInfoImpl_getPerfStatsDispatcher(this: ITraceSweepInfo): IPerformanceStats; cdecl; +begin + Result := nil; + try + Result := ITraceSweepInfoImpl(this).getPerfStats(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + var ITraceSweepInfoImpl_vTable: TraceSweepInfoVTable; @@ -17543,6 +17837,112 @@ constructor IProfilerStatsImpl.create; vTable := IProfilerStatsImpl_vTable; end; +function IPerformanceCountersImpl_getObjectCountDispatcher(this: IPerformanceCounters): Cardinal; cdecl; +begin + Result := 0; + try + Result := IPerformanceCountersImpl(this).getObjectCount(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceCountersImpl_getCountersCapacityDispatcher(this: IPerformanceCounters): Cardinal; cdecl; +begin + Result := 0; + try + Result := IPerformanceCountersImpl(this).getCountersCapacity(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceCountersImpl_getObjectIdDispatcher(this: IPerformanceCounters; index: Cardinal): Cardinal; cdecl; +begin + Result := 0; + try + Result := IPerformanceCountersImpl(this).getObjectId(index); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceCountersImpl_getObjectNameDispatcher(this: IPerformanceCounters; index: Cardinal): PAnsiChar; cdecl; +begin + Result := nil; + try + Result := IPerformanceCountersImpl(this).getObjectName(index); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceCountersImpl_getObjectCountersDispatcher(this: IPerformanceCounters; index: Cardinal): Int64Ptr; cdecl; +begin + Result := nil; + try + Result := IPerformanceCountersImpl(this).getObjectCounters(index); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +var + IPerformanceCountersImpl_vTable: PerformanceCountersVTable; + +constructor IPerformanceCountersImpl.create; +begin + vTable := IPerformanceCountersImpl_vTable; +end; + +function IPerformanceStatsImpl_getElapsedTimeDispatcher(this: IPerformanceStats): QWord; cdecl; +begin + Result := 0; + try + Result := IPerformanceStatsImpl(this).getElapsedTime(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceStatsImpl_getFetchedRecordsDispatcher(this: IPerformanceStats): QWord; cdecl; +begin + Result := 0; + try + Result := IPerformanceStatsImpl(this).getFetchedRecords(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceStatsImpl_getPageCountersDispatcher(this: IPerformanceStats): IPerformanceCounters; cdecl; +begin + Result := nil; + try + Result := IPerformanceStatsImpl(this).getPageCounters(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +function IPerformanceStatsImpl_getTableCountersDispatcher(this: IPerformanceStats): IPerformanceCounters; cdecl; +begin + Result := nil; + try + Result := IPerformanceStatsImpl(this).getTableCounters(); + except + on e: Exception do FbException.catchException(nil, e); + end +end; + +var + IPerformanceStatsImpl_vTable: PerformanceStatsVTable; + +constructor IPerformanceStatsImpl.create; +begin + vTable := IPerformanceStatsImpl_vTable; +end; + constructor FbException.create(status: IStatus); begin inherited Create('FbException'); @@ -18308,7 +18708,7 @@ initialization ITraceDatabaseConnectionImpl_vTable.getDatabaseName := @ITraceDatabaseConnectionImpl_getDatabaseNameDispatcher; ITraceTransactionImpl_vTable := TraceTransactionVTable.create; - ITraceTransactionImpl_vTable.version := 3; + ITraceTransactionImpl_vTable.version := 4; ITraceTransactionImpl_vTable.getTransactionID := @ITraceTransactionImpl_getTransactionIDDispatcher; ITraceTransactionImpl_vTable.getReadOnly := @ITraceTransactionImpl_getReadOnlyDispatcher; ITraceTransactionImpl_vTable.getWait := @ITraceTransactionImpl_getWaitDispatcher; @@ -18316,6 +18716,7 @@ initialization ITraceTransactionImpl_vTable.getPerf := @ITraceTransactionImpl_getPerfDispatcher; ITraceTransactionImpl_vTable.getInitialID := @ITraceTransactionImpl_getInitialIDDispatcher; ITraceTransactionImpl_vTable.getPreviousID := @ITraceTransactionImpl_getPreviousIDDispatcher; + ITraceTransactionImpl_vTable.getPerfStats := @ITraceTransactionImpl_getPerfStatsDispatcher; ITraceParamsImpl_vTable := TraceParamsVTable.create; ITraceParamsImpl_vTable.version := 3; @@ -18324,14 +18725,16 @@ initialization ITraceParamsImpl_vTable.getTextUTF8 := @ITraceParamsImpl_getTextUTF8Dispatcher; ITraceStatementImpl_vTable := TraceStatementVTable.create; - ITraceStatementImpl_vTable.version := 2; + ITraceStatementImpl_vTable.version := 3; ITraceStatementImpl_vTable.getStmtID := @ITraceStatementImpl_getStmtIDDispatcher; ITraceStatementImpl_vTable.getPerf := @ITraceStatementImpl_getPerfDispatcher; + ITraceStatementImpl_vTable.getPerfStats := @ITraceStatementImpl_getPerfStatsDispatcher; ITraceSQLStatementImpl_vTable := TraceSQLStatementVTable.create; - ITraceSQLStatementImpl_vTable.version := 3; + ITraceSQLStatementImpl_vTable.version := 4; ITraceSQLStatementImpl_vTable.getStmtID := @ITraceSQLStatementImpl_getStmtIDDispatcher; ITraceSQLStatementImpl_vTable.getPerf := @ITraceSQLStatementImpl_getPerfDispatcher; + ITraceSQLStatementImpl_vTable.getPerfStats := @ITraceSQLStatementImpl_getPerfStatsDispatcher; ITraceSQLStatementImpl_vTable.getText := @ITraceSQLStatementImpl_getTextDispatcher; ITraceSQLStatementImpl_vTable.getPlan := @ITraceSQLStatementImpl_getPlanDispatcher; ITraceSQLStatementImpl_vTable.getInputs := @ITraceSQLStatementImpl_getInputsDispatcher; @@ -18339,9 +18742,10 @@ initialization ITraceSQLStatementImpl_vTable.getExplainedPlan := @ITraceSQLStatementImpl_getExplainedPlanDispatcher; ITraceBLRStatementImpl_vTable := TraceBLRStatementVTable.create; - ITraceBLRStatementImpl_vTable.version := 3; + ITraceBLRStatementImpl_vTable.version := 4; ITraceBLRStatementImpl_vTable.getStmtID := @ITraceBLRStatementImpl_getStmtIDDispatcher; ITraceBLRStatementImpl_vTable.getPerf := @ITraceBLRStatementImpl_getPerfDispatcher; + ITraceBLRStatementImpl_vTable.getPerfStats := @ITraceBLRStatementImpl_getPerfStatsDispatcher; ITraceBLRStatementImpl_vTable.getData := @ITraceBLRStatementImpl_getDataDispatcher; ITraceBLRStatementImpl_vTable.getDataLength := @ITraceBLRStatementImpl_getDataLengthDispatcher; ITraceBLRStatementImpl_vTable.getText := @ITraceBLRStatementImpl_getTextDispatcher; @@ -18359,16 +18763,17 @@ initialization ITraceContextVariableImpl_vTable.getVarValue := @ITraceContextVariableImpl_getVarValueDispatcher; ITraceProcedureImpl_vTable := TraceProcedureVTable.create; - ITraceProcedureImpl_vTable.version := 3; + ITraceProcedureImpl_vTable.version := 4; ITraceProcedureImpl_vTable.getProcName := @ITraceProcedureImpl_getProcNameDispatcher; ITraceProcedureImpl_vTable.getInputs := @ITraceProcedureImpl_getInputsDispatcher; ITraceProcedureImpl_vTable.getPerf := @ITraceProcedureImpl_getPerfDispatcher; ITraceProcedureImpl_vTable.getStmtID := @ITraceProcedureImpl_getStmtIDDispatcher; ITraceProcedureImpl_vTable.getPlan := @ITraceProcedureImpl_getPlanDispatcher; ITraceProcedureImpl_vTable.getExplainedPlan := @ITraceProcedureImpl_getExplainedPlanDispatcher; + ITraceProcedureImpl_vTable.getPerfStats := @ITraceProcedureImpl_getPerfStatsDispatcher; ITraceFunctionImpl_vTable := TraceFunctionVTable.create; - ITraceFunctionImpl_vTable.version := 3; + ITraceFunctionImpl_vTable.version := 4; ITraceFunctionImpl_vTable.getFuncName := @ITraceFunctionImpl_getFuncNameDispatcher; ITraceFunctionImpl_vTable.getInputs := @ITraceFunctionImpl_getInputsDispatcher; ITraceFunctionImpl_vTable.getResult := @ITraceFunctionImpl_getResultDispatcher; @@ -18376,9 +18781,10 @@ initialization ITraceFunctionImpl_vTable.getStmtID := @ITraceFunctionImpl_getStmtIDDispatcher; ITraceFunctionImpl_vTable.getPlan := @ITraceFunctionImpl_getPlanDispatcher; ITraceFunctionImpl_vTable.getExplainedPlan := @ITraceFunctionImpl_getExplainedPlanDispatcher; + ITraceFunctionImpl_vTable.getPerfStats := @ITraceFunctionImpl_getPerfStatsDispatcher; ITraceTriggerImpl_vTable := TraceTriggerVTable.create; - ITraceTriggerImpl_vTable.version := 3; + ITraceTriggerImpl_vTable.version := 4; ITraceTriggerImpl_vTable.getTriggerName := @ITraceTriggerImpl_getTriggerNameDispatcher; ITraceTriggerImpl_vTable.getRelationName := @ITraceTriggerImpl_getRelationNameDispatcher; ITraceTriggerImpl_vTable.getAction := @ITraceTriggerImpl_getActionDispatcher; @@ -18387,6 +18793,7 @@ initialization ITraceTriggerImpl_vTable.getStmtID := @ITraceTriggerImpl_getStmtIDDispatcher; ITraceTriggerImpl_vTable.getPlan := @ITraceTriggerImpl_getPlanDispatcher; ITraceTriggerImpl_vTable.getExplainedPlan := @ITraceTriggerImpl_getExplainedPlanDispatcher; + ITraceTriggerImpl_vTable.getPerfStats := @ITraceTriggerImpl_getPerfStatsDispatcher; ITraceServiceConnectionImpl_vTable := TraceServiceConnectionVTable.create; ITraceServiceConnectionImpl_vTable.version := 3; @@ -18411,12 +18818,13 @@ initialization ITraceStatusVectorImpl_vTable.getText := @ITraceStatusVectorImpl_getTextDispatcher; ITraceSweepInfoImpl_vTable := TraceSweepInfoVTable.create; - ITraceSweepInfoImpl_vTable.version := 2; + ITraceSweepInfoImpl_vTable.version := 3; ITraceSweepInfoImpl_vTable.getOIT := @ITraceSweepInfoImpl_getOITDispatcher; ITraceSweepInfoImpl_vTable.getOST := @ITraceSweepInfoImpl_getOSTDispatcher; ITraceSweepInfoImpl_vTable.getOAT := @ITraceSweepInfoImpl_getOATDispatcher; ITraceSweepInfoImpl_vTable.getNext := @ITraceSweepInfoImpl_getNextDispatcher; ITraceSweepInfoImpl_vTable.getPerf := @ITraceSweepInfoImpl_getPerfDispatcher; + ITraceSweepInfoImpl_vTable.getPerfStats := @ITraceSweepInfoImpl_getPerfStatsDispatcher; ITraceLogWriterImpl_vTable := TraceLogWriterVTable.create; ITraceLogWriterImpl_vTable.version := 4; @@ -18600,6 +19008,21 @@ initialization IProfilerStatsImpl_vTable.version := 2; IProfilerStatsImpl_vTable.getElapsedTicks := @IProfilerStatsImpl_getElapsedTicksDispatcher; + IPerformanceCountersImpl_vTable := PerformanceCountersVTable.create; + IPerformanceCountersImpl_vTable.version := 2; + IPerformanceCountersImpl_vTable.getObjectCount := @IPerformanceCountersImpl_getObjectCountDispatcher; + IPerformanceCountersImpl_vTable.getCountersCapacity := @IPerformanceCountersImpl_getCountersCapacityDispatcher; + IPerformanceCountersImpl_vTable.getObjectId := @IPerformanceCountersImpl_getObjectIdDispatcher; + IPerformanceCountersImpl_vTable.getObjectName := @IPerformanceCountersImpl_getObjectNameDispatcher; + IPerformanceCountersImpl_vTable.getObjectCounters := @IPerformanceCountersImpl_getObjectCountersDispatcher; + + IPerformanceStatsImpl_vTable := PerformanceStatsVTable.create; + IPerformanceStatsImpl_vTable.version := 2; + IPerformanceStatsImpl_vTable.getElapsedTime := @IPerformanceStatsImpl_getElapsedTimeDispatcher; + IPerformanceStatsImpl_vTable.getFetchedRecords := @IPerformanceStatsImpl_getFetchedRecordsDispatcher; + IPerformanceStatsImpl_vTable.getPageCounters := @IPerformanceStatsImpl_getPageCountersDispatcher; + IPerformanceStatsImpl_vTable.getTableCounters := @IPerformanceStatsImpl_getTableCountersDispatcher; + finalization IVersionedImpl_vTable.destroy; IReferenceCountedImpl_vTable.destroy; @@ -18699,5 +19122,7 @@ finalization IProfilerPluginImpl_vTable.destroy; IProfilerSessionImpl_vTable.destroy; IProfilerStatsImpl_vTable.destroy; + IPerformanceCountersImpl_vTable.destroy; + IPerformanceStatsImpl_vTable.destroy; end. diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index ea09c3daa32..07f64418679 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -1451,36 +1451,39 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt // logical I/O statistics (table wise) - for (auto iter(statistics.getRelCounters()); iter; ++iter) + for (const auto& counts : statistics.getTableCounters()) { + if (counts.isEmpty()) + continue; + const auto rec_stat_id = getGlobalId(fb_utils::genUniqueId()); record.reset(rel_mon_tab_stats); record.storeGlobalId(f_mon_tab_stat_id, id); record.storeInteger(f_mon_tab_stat_group, stat_group); - record.storeTableIdSchemaName(f_mon_tab_sch_name, (*iter).getRelationId()); - record.storeTableIdObjectName(f_mon_tab_name, (*iter).getRelationId()); + record.storeTableIdSchemaName(f_mon_tab_sch_name, counts.getGroupId()); + record.storeTableIdObjectName(f_mon_tab_name, counts.getGroupId()); record.storeGlobalId(f_mon_tab_rec_stat_id, rec_stat_id); record.write(); 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)[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.storeInteger(f_mon_rec_seq_reads, counts[RecordStatType::SEQ_READS]); + record.storeInteger(f_mon_rec_idx_reads, counts[RecordStatType::IDX_READS]); + record.storeInteger(f_mon_rec_inserts, counts[RecordStatType::INSERTS]); + record.storeInteger(f_mon_rec_updates, counts[RecordStatType::UPDATES]); + record.storeInteger(f_mon_rec_deletes, counts[RecordStatType::DELETES]); + record.storeInteger(f_mon_rec_backouts, counts[RecordStatType::BACKOUTS]); + record.storeInteger(f_mon_rec_purges, counts[RecordStatType::PURGES]); + record.storeInteger(f_mon_rec_expunges, counts[RecordStatType::EXPUNGES]); + record.storeInteger(f_mon_rec_locks, counts[RecordStatType::LOCKS]); + record.storeInteger(f_mon_rec_waits, counts[RecordStatType::WAITS]); + record.storeInteger(f_mon_rec_conflicts, counts[RecordStatType::CONFLICTS]); + record.storeInteger(f_mon_rec_bkver_reads, counts[RecordStatType::BACK_READS]); + record.storeInteger(f_mon_rec_frg_reads, counts[RecordStatType::FRAGMENT_READS]); + record.storeInteger(f_mon_rec_rpt_reads, counts[RecordStatType::RPT_READS]); + record.storeInteger(f_mon_rec_imgc, counts[RecordStatType::IMGC]); record.write(); } } diff --git a/src/jrd/RuntimeStatistics.cpp b/src/jrd/RuntimeStatistics.cpp index 95630662623..d4ce6474d6f 100644 --- a/src/jrd/RuntimeStatistics.cpp +++ b/src/jrd/RuntimeStatistics.cpp @@ -33,52 +33,75 @@ namespace Jrd { GlobalPtr RuntimeStatistics::dummy; -void RuntimeStatistics::adjustRelStats(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) +void RuntimeStatistics::adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats) { - if (baseStats.relChgNumber == newStats.relChgNumber) + if (baseStats.allChgNumber == newStats.allChgNumber) return; - relChgNumber++; + allChgNumber++; + for (size_t i = 0; i < GLOBAL_ITEMS; ++i) + values[i] += newStats.values[i] - baseStats.values[i]; + + if (baseStats.pageChgNumber != newStats.pageChgNumber) + { + pageChgNumber++; + pageCounters.adjust(baseStats.pageCounters, newStats.pageCounters); + } + + if (baseStats.tabChgNumber != newStats.tabChgNumber) + { + tabChgNumber++; + tableCounters.adjust(baseStats.tableCounters, newStats.tableCounters); + } +} - auto locate = [this](SLONG relId) -> FB_SIZE_T +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) { - FB_SIZE_T pos; - if (!rel_counts.find(relId, pos)) - rel_counts.insert(pos, RelationCounts(relId)); - return pos; - }; + const SINT64 delta = newStats.values[i] - baseStats.values[i]; - auto baseIter = baseStats.rel_counts.begin(), newIter = newStats.rel_counts.begin(); - const auto baseEnd = baseStats.rel_counts.end(), newEnd = newStats.rel_counts.end(); + values[i] += delta; + baseStats.values[i] += delta; + } +} + +template +void RuntimeStatistics::GroupedCountsArray::adjust(const GroupedCountsArray& baseStats, const GroupedCountsArray& newStats) +{ + auto baseIter = baseStats.m_counts.begin(), newIter = newStats.m_counts.begin(); + const auto baseEnd = baseStats.m_counts.end(), newEnd = newStats.m_counts.end(); - // The loop below assumes that newStats cannot miss relations existing in baseStats, + // The loop below assumes that newStats cannot miss objects 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) { - // Relation exists in newStats but missing in baseStats - const auto newRelId = newIter->getRelationId(); - rel_counts[locate(newRelId)] += *newIter++; + // Object exists in newStats but missing in baseStats + const auto newId = newIter->getGroupId(); + (*this)[newId] += *newIter++; } else if (newIter != newEnd) { - const auto baseRelId = baseIter->getRelationId(); - const auto newRelId = newIter->getRelationId(); + const auto baseId = baseIter->getGroupId(); + const auto newId = newIter->getGroupId(); - if (newRelId == baseRelId) + if (newId == baseId) { - // Relation exists in both newStats and baseStats - fb_assert(baseRelId == newRelId); - const auto pos = locate(baseRelId); - rel_counts[pos] -= *baseIter++; - rel_counts[pos] += *newIter++; + // Object exists in both newStats and baseStats + (*this)[newId] += *newIter++; + (*this)[newId] -= *baseIter++; } - else if (newRelId < baseRelId) + else if (newId < baseId) { - // Relation exists in newStats but missing in baseStats - rel_counts[locate(newRelId)] += *newIter++; + // Object exists in newStats but missing in baseStats + (*this)[newId] += *newIter++; } else fb_assert(false); // should never happen @@ -88,114 +111,23 @@ void RuntimeStatistics::adjustRelStats(const RuntimeStatistics& baseStats, const } } -PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, - const RuntimeStatistics& new_stat, - PerformanceInfo& dest, - TraceCountsArray& temp, - ObjectsArray& tempNames) +void RuntimeStatistics::setToDiff(const RuntimeStatistics& newStats) { - // NOTE: we do not initialize dest.pin_time. This must be done by the caller - - // Calculate database-level statistics for (size_t i = 0; i < GLOBAL_ITEMS; i++) - values[i] = new_stat.values[i] - values[i]; + values[i] = newStats.values[i] - values[i]; - dest.pin_counters = values; - - // Calculate relation-level statistics - temp.clear(); - tempNames.clear(); - - // This loop assumes that base array is smaller than new one - RelCounters::iterator base_cnts = rel_counts.begin(); - bool base_found = (base_cnts != rel_counts.end()); - - for (const auto& new_cnts : new_stat.rel_counts) + for (const auto& newCounts : newStats.pageCounters) { - 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)) - { - jrd_rel* const relation = - rel_id < static_cast(att->att_relations->count()) ? - (*att->att_relations)[rel_id] : NULL; - - TraceCounts traceCounts; - traceCounts.trc_relation_id = rel_id; - traceCounts.trc_counters = base_cnts->getCounterVector(); - - if (relation) - { - auto& tempName = tempNames.add(); - tempName = relation->rel_name.toQuotedString(); - traceCounts.trc_relation_name = tempName.c_str(); - } - else - traceCounts.trc_relation_name = nullptr; - - temp.add(traceCounts); - } - - ++base_cnts; - base_found = (base_cnts != rel_counts.end()); - } - else - { - jrd_rel* const relation = - rel_id < static_cast(att->att_relations->count()) ? - (*att->att_relations)[rel_id] : NULL; - - // Point TraceCounts to counts array from object with updated counters - TraceCounts traceCounts; - traceCounts.trc_relation_id = rel_id; - traceCounts.trc_counters = new_cnts.getCounterVector(); - - if (relation) - { - auto& tempName = tempNames.add(); - tempName = relation->rel_name.toQuotedString(); - traceCounts.trc_relation_name = tempName.c_str(); - } - else - traceCounts.trc_relation_name = nullptr; - - temp.add(traceCounts); - } - }; - - dest.pin_count = temp.getCount(); - dest.pin_tables = temp.begin(); - - return &dest; -} - -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; + const auto pageSpaceId = newCounts.getGroupId(); + if (!pageCounters[pageSpaceId].setToDiff(newCounts)) + pageCounters.remove(pageSpaceId); + } - allChgNumber++; - for (size_t i = 0; i < PAGE_TOTAL_ITEMS; ++i) + for (const auto& newCounts : newStats.tableCounters) { - const SINT64 delta = newStats.values[i] - baseStats.values[i]; - - values[i] += delta; - baseStats.values[i] += delta; + const auto relationId = newCounts.getGroupId(); + if (!tableCounters[relationId].setToDiff(newCounts)) + tableCounters.remove(relationId); } } diff --git a/src/jrd/RuntimeStatistics.h b/src/jrd/RuntimeStatistics.h index d340cd0d079..3db58932ab0 100644 --- a/src/jrd/RuntimeStatistics.h +++ b/src/jrd/RuntimeStatistics.h @@ -29,19 +29,11 @@ #include "../common/classes/init.h" #include "../common/classes/tree.h" #include "../common/classes/File.h" +#include "../jrd/ini.h" +#include "../jrd/pag.h" #include -namespace Firebird -{ - -// declared in firebird/Interface.h -struct TraceCounts; -struct PerformanceInfo; - -} // namespace Firebird - - namespace Jrd { class Attachment; @@ -49,7 +41,6 @@ class Database; class thread_db; class jrd_rel; -typedef Firebird::HalfStaticArray TraceCountsArray; // Runtime statistics @@ -92,7 +83,7 @@ class RuntimeStatistics : protected Firebird::AutoStorage // // 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 + // as they may be aggregated from the tableCounters 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. @@ -135,6 +126,24 @@ class RuntimeStatistics : protected Firebird::AutoStorage return *this; } + bool setToDiff(const CountsVector& other) + { + bool ret = false; + + for (size_t i = 0; i < m_counters.size(); i++) + { + if ( (m_counters[i] = other.m_counters[i] - m_counters[i]) ) + ret = true; + } + + return ret; + } + + static unsigned getVectorCapacity() + { + return (unsigned) SIZE; + } + const SINT64* getCounterVector() const { return m_counters.data(); @@ -156,104 +165,187 @@ class RuntimeStatistics : protected Firebird::AutoStorage std::array m_counters = {}; }; - // Performance counters for individual table - - class RelationCounts : public CountsVector + template + class CountsGroup : public CountsVector { public: - explicit RelationCounts(SLONG relation_id) - : m_relation_id(relation_id) + typedef Key ID; + + explicit CountsGroup(ID id) + : m_id(id) + {} + + ID getGroupId() const { + return m_id; } - SLONG getRelationId() const + CountsGroup& operator+=(const CountsGroup& other) { - return m_relation_id; + fb_assert(m_id == other.m_id); + CountsVector::operator+=(other); + return *this; } - bool setToDiff(const RelationCounts& other) + CountsGroup& operator-=(const CountsGroup& other) { - fb_assert(m_relation_id == other.m_relation_id); + fb_assert(m_id == other.m_id); + CountsVector::operator-=(other); + return *this; + } - bool ret = false; + bool setToDiff(const CountsGroup& other) + { + fb_assert(m_id == other.m_id); + return CountsVector::setToDiff(other); + } - for (size_t i = 0; i < m_counters.size(); i++) + inline static const ID& generate(const CountsGroup& item) + { + return item.m_id; + } + + private: + ID m_id; + }; + + template + class GroupedCountsArray + { + typedef typename Counts::ID ID; + typedef Firebird::SortedArray< + Counts, Firebird::EmptyStorage, ID, Counts> SortedCountsArray; + typedef typename SortedCountsArray::const_iterator ConstIterator; + + public: + GroupedCountsArray(MemoryPool& pool, FB_SIZE_T capacity) + : m_counts(pool, capacity) + {} + + GroupedCountsArray(MemoryPool& pool, const GroupedCountsArray& other) + : m_counts(pool, other.m_counts.getCapacity()) + {} + + Counts& operator[](ID id) + { + if ((m_lastPos != (FB_SIZE_T) ~0 && m_counts[m_lastPos].getGroupId() == id) || + // if m_lastPos is mispositioned + m_counts.find(id, m_lastPos)) { - if ( (m_counters[i] = other.m_counters[i] - m_counters[i]) ) - ret = true; + return m_counts[m_lastPos]; } - return ret; + Counts counts(id); + m_counts.insert(m_lastPos, counts); + return m_counts[m_lastPos]; } - RelationCounts& operator+=(const RelationCounts& other) + unsigned getCount() const { - fb_assert(m_relation_id == other.m_relation_id); - CountsVector::operator+=(other); - return *this; + return m_counts.getCount(); } - RelationCounts& operator-=(const RelationCounts& other) + static unsigned getVectorCapacity() { - fb_assert(m_relation_id == other.m_relation_id); - CountsVector::operator-=(other); - return *this; + return Counts::getVectorCapacity(); + } + + void remove(ID id) + { + if ((m_lastPos != (FB_SIZE_T) ~0 && m_counts[m_lastPos].getGroupId() == id) || + // if m_lastPos is mispositioned + m_counts.find(id, m_lastPos)) + { + m_counts.remove(m_lastPos); + m_lastPos = (FB_SIZE_T) ~0; + } + } + + void reset() + { + m_counts.clear(); + m_lastPos = (FB_SIZE_T) ~0; } - inline static const SLONG& generate(const RelationCounts& item) + ConstIterator begin() const { - return item.m_relation_id; + return m_counts.begin(); } + ConstIterator end() const + { + return m_counts.end(); + } + + void adjust(const GroupedCountsArray& baseStats, const GroupedCountsArray& newStats); + private: - SLONG m_relation_id; + SortedCountsArray m_counts; + FB_SIZE_T m_lastPos = (FB_SIZE_T) ~0; }; - typedef Firebird::SortedArray, - SLONG, RelationCounts> RelCounters; - public: + typedef GroupedCountsArray > PageCounters; + typedef GroupedCountsArray > TableCounters; + RuntimeStatistics() - : Firebird::AutoStorage(), rel_counts(getPool()) + : Firebird::AutoStorage(), + pageCounters(getPool(), DB_PAGE_SPACE + 1), + tableCounters(getPool(), rel_MAX) { reset(); } explicit RuntimeStatistics(MemoryPool& pool) - : Firebird::AutoStorage(pool), rel_counts(getPool()) + : Firebird::AutoStorage(pool), + pageCounters(getPool(), DB_PAGE_SPACE + 1), + tableCounters(getPool(), rel_MAX) { reset(); } RuntimeStatistics(const RuntimeStatistics& other) - : Firebird::AutoStorage(), rel_counts(getPool()) + : Firebird::AutoStorage(), + pageCounters(getPool(), other.pageCounters), + tableCounters(getPool(), other.tableCounters) { memcpy(values, other.values, sizeof(values)); - rel_counts = other.rel_counts; + + pageCounters = other.pageCounters; + tableCounters = other.tableCounters; allChgNumber = other.allChgNumber; - relChgNumber = other.relChgNumber; + pageChgNumber = other.pageChgNumber; + tabChgNumber = other.tabChgNumber; } RuntimeStatistics(MemoryPool& pool, const RuntimeStatistics& other) - : Firebird::AutoStorage(pool), rel_counts(getPool()) + : Firebird::AutoStorage(pool), + pageCounters(getPool(), other.pageCounters), + tableCounters(getPool(), other.tableCounters) { memcpy(values, other.values, sizeof(values)); - rel_counts = other.rel_counts; + + pageCounters = other.pageCounters; + tableCounters = other.tableCounters; allChgNumber = other.allChgNumber; - relChgNumber = other.relChgNumber; + pageChgNumber = other.pageChgNumber; + tabChgNumber = other.tabChgNumber; } ~RuntimeStatistics() = default; void reset() { - memset(values, 0, sizeof values); - rel_counts.clear(); - rel_last_pos = (FB_SIZE_T) ~0; + memset(values, 0, sizeof(values)); + + pageCounters.reset(); + tableCounters.reset(); + allChgNumber = 0; - relChgNumber = 0; + pageChgNumber = 0; + tabChgNumber = 0; } const SINT64& operator[](const PageStatType type) const @@ -262,11 +354,17 @@ class RuntimeStatistics : protected Firebird::AutoStorage return values[index]; } - void bumpValue(const PageStatType type, SINT64 delta = 1) + void bumpValue(const PageStatType type, ULONG pageSpaceId, SINT64 delta = 1) { + ++allChgNumber; const auto index = static_cast(type); values[index] += delta; - ++allChgNumber; + + if (isValid()) // optimization for non-trivial data access + { + ++pageChgNumber; + pageCounters[pageSpaceId][type] += delta; + } } const SINT64& operator[](const RecordStatType type) const @@ -279,42 +377,28 @@ class RuntimeStatistics : protected Firebird::AutoStorage { SINT64 value = 0; - for (const auto& counts : rel_counts) + for (const auto& counts : tableCounters) value += counts[type]; return value; } - void bumpValue(const RecordStatType type, SINT64 delta = 1) + void bumpValue(const RecordStatType type, SLONG relationId, SINT64 delta = 1) { + ++allChgNumber; 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) || - // if rel_last_pos is mispositioned - rel_counts.find(relation_id, rel_last_pos)) - { - rel_counts[rel_last_pos][type] += delta; - } - else + if (isValid()) // optimization for non-trivial data access { - RelationCounts counts(relation_id); - counts[type] += delta; - rel_counts.insert(rel_last_pos, counts); + ++tabChgNumber; + tableCounters[relationId][type] += 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); + void setToDiff(const RuntimeStatistics& newStats); // Add difference between newStats and baseStats to our counters // (newStats and baseStats must be "in-sync") @@ -331,16 +415,27 @@ class RuntimeStatistics : protected Firebird::AutoStorage memcpy(values, other.values, sizeof(values)); allChgNumber = other.allChgNumber; - if (relChgNumber != other.relChgNumber) + if (pageChgNumber != other.pageChgNumber) { - rel_counts = other.rel_counts; - relChgNumber = other.relChgNumber; + pageCounters = other.pageCounters; + pageChgNumber = other.pageChgNumber; + } + + if (tabChgNumber != other.tabChgNumber) + { + tableCounters = other.tableCounters; + tabChgNumber = other.tabChgNumber; } } return *this; } + bool isValid() const + { + return (this != &dummy); + } + static RuntimeStatistics* getDummy() { return &dummy; @@ -364,62 +459,28 @@ class RuntimeStatistics : protected Firebird::AutoStorage SINT64 m_counter = 0; }; - template class Iterator + const PageCounters& getPageCounters() const { - public: - explicit Iterator(const T& counts) - : m_iter(counts.begin()), m_end(counts.end()) - { - advance(); - } - - void operator++() - { - m_iter++; - advance(); - } - - typename T::const_reference operator*() const - { - return *m_iter; - } - - operator bool() const - { - return (m_iter != m_end); - } - - private: - typename T::const_iterator m_iter; - const typename T::const_iterator m_end; - - void advance() - { - while (m_iter != m_end && m_iter->isEmpty()) - m_iter++; - } - }; - - typedef Iterator RelationIterator; + return pageCounters; + } - RelationIterator getRelCounters() const + const TableCounters& getTableCounters() const { - return RelationIterator(rel_counts); + return tableCounters; } private: - void adjustRelStats(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats); - SINT64 values[GLOBAL_ITEMS]; - RelCounters rel_counts; - FB_SIZE_T rel_last_pos; + PageCounters pageCounters; + TableCounters tableCounters; - // These three numbers are used in adjust() and assign() methods as "generation" + // These 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. ULONG allChgNumber; // incremented when any counter changes - ULONG relChgNumber; // incremented when relation counter changes + ULONG pageChgNumber; // incremented when page counter changes + ULONG tabChgNumber; // incremented when table counter changes // This dummy RuntimeStatistics is used instead of missing elements in tdbb, // helping us to avoid conditional checks in time-critical places of code. diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp index d660ce17bf1..ecb7ed947bb 100644 --- a/src/jrd/cch.cpp +++ b/src/jrd/cch.cpp @@ -930,9 +930,10 @@ 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(PageStatType::READS); + const ULONG pageSpaceId = bdb->bdb_page.getPageSpaceID(); + tdbb->bumpStats(PageStatType::READS, pageSpaceId); - PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(bdb->bdb_page.getPageSpaceID()); + const auto pageSpace = dbb->dbb_page_manager.findPageSpace(pageSpaceId); fb_assert(pageSpace); jrd_file* file = pageSpace->file; @@ -1011,7 +1012,7 @@ void CCH_fetch_page(thread_db* tdbb, WIN* window, const bool read_shadow) { diff_page = bm->getPageIndex(tdbb, bdb->bdb_page.getPageNum()); NBAK_TRACE(("Reading page %d:%06d, state=%d, diff page=%d", - bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); + pageSpaceId, bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); } // In merge mode, if we are reading past beyond old end of file and page is in .delta file @@ -1021,7 +1022,7 @@ void CCH_fetch_page(thread_db* tdbb, WIN* window, const bool read_shadow) fb_assert(bdb->bdb_page == window->win_page); NBAK_TRACE(("Reading page %d:%06d, state=%d, diff page=%d from DISK", - bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); + pageSpaceId, bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); // Read page from disk as normal Pio io(file, bdb, isTempPage, read_shadow, pageSpace); @@ -1701,14 +1702,16 @@ void CCH_mark(thread_db* tdbb, WIN* window, bool mark_system, bool must_write) SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); - tdbb->bumpStats(PageStatType::MARKS); + + const ULONG pageSpaceId = window->win_page.getPageSpaceID(); + tdbb->bumpStats(PageStatType::MARKS, pageSpaceId); BufferControl* bcb = dbb->dbb_bcb; if (!(bdb->bdb_flags & BDB_writer)) BUGCHECK(208); // msg 208 page not accessed for write - CCH_TRACE(("MARK %d:%06d", window->win_page.getPageSpaceID(), window->win_page.getPageNum())); + CCH_TRACE(("MARK %d:%06d", pageSpaceId, window->win_page.getPageNum())); // A LATCH_mark is needed before the BufferDesc can be marked. // This prevents a write while the page is being modified. @@ -3805,6 +3808,8 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s BufferControl* bcb = dbb->dbb_bcb; Attachment* att = tdbb->getAttachment(); + const ULONG pageSpaceId = page.getPageSpaceID(); + if (att && att->att_bdb_cache) { if (BufferDesc* bdb = att->att_bdb_cache->get(page)) @@ -3814,7 +3819,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s if (bdb->bdb_page == page) { recentlyUsed(bdb); - tdbb->bumpStats(PageStatType::FETCHES); + tdbb->bumpStats(PageStatType::FETCHES, pageSpaceId); return bdb; } @@ -3857,7 +3862,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s if (bdb->bdb_page == page) { recentlyUsed(bdb); - tdbb->bumpStats(PageStatType::FETCHES); + tdbb->bumpStats(PageStatType::FETCHES, pageSpaceId); cacheBuffer(att, bdb); return bdb; } @@ -3897,7 +3902,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s { bdb->downgrade(syncType); recentlyUsed(bdb); - tdbb->bumpStats(PageStatType::FETCHES); + tdbb->bumpStats(PageStatType::FETCHES, pageSpaceId); cacheBuffer(att, bdb); return bdb; } @@ -3941,7 +3946,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s else recentlyUsed(bdb); } - tdbb->bumpStats(PageStatType::FETCHES); + tdbb->bumpStats(PageStatType::FETCHES, pageSpaceId); cacheBuffer(att, bdb); return bdb; } @@ -3959,7 +3964,7 @@ static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s continue; } recentlyUsed(bdb2); - tdbb->bumpStats(PageStatType::FETCHES); + tdbb->bumpStats(PageStatType::FETCHES, pageSpaceId); cacheBuffer(att, bdb2); } else @@ -4914,7 +4919,8 @@ 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(PageStatType::WRITES); + const ULONG pageSpaceId = bdb->bdb_page.getPageSpaceID(); + tdbb->bumpStats(PageStatType::WRITES, pageSpaceId); // write out page to main database file, and to any // shadows, making a special case of the header page @@ -4952,8 +4958,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s gds__trace(buffer); #endif - PageSpace* pageSpace = - dbb->dbb_page_manager.findPageSpace(bdb->bdb_page.getPageSpaceID()); + const auto pageSpace = dbb->dbb_page_manager.findPageSpace(pageSpaceId); fb_assert(pageSpace); const bool isTempPage = pageSpace->isTemporary(); diff --git a/src/jrd/inf.cpp b/src/jrd/inf.cpp index 7d0d42b9eb6..60f0b6a29bd 100644 --- a/src/jrd/inf.cpp +++ b/src/jrd/inf.cpp @@ -273,11 +273,11 @@ void INF_database_info(thread_db* tdbb, resultBuffer.clear(); FB_SIZE_T bufferLength = 0; - for (auto iter(recordStats->getRelCounters()); iter; ++iter) + for (const auto& counts : recordStats->getTableCounters()) { - if (const SINT64 n = (*iter)[type]) + if (const SINT64 n = counts[type]) { - const USHORT relationId = (*iter).getRelationId(); + const USHORT relationId = counts.getGroupId(); const USHORT length = INF_convert(n, numBuffer); const FB_SIZE_T newBufferLength = bufferLength + length + sizeof(USHORT); resultBuffer.grow(newBufferLength); diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index 2e3644c89cc..d6b2896c0db 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -612,44 +612,35 @@ class thread_db final : public Firebird::ThreadData tdbb_flags |= TDBB_sweeper; } - void bumpStats(const PageStatType type, SINT64 delta = 1) + void bumpStats(const PageStatType type, ULONG pageSpaceId, SINT64 delta = 1) { - reqStat->bumpValue(type, delta); - traStat->bumpValue(type, delta); - attStat->bumpValue(type, delta); + fb_assert(pageSpaceId != INVALID_PAGE_SPACE); + + // [0] element stores statistics for temporary page spaces + if (PageSpace::isTemporary(pageSpaceId)) + pageSpaceId = 0; + + reqStat->bumpValue(type, pageSpaceId, delta); + traStat->bumpValue(type, pageSpaceId, delta); + attStat->bumpValue(type, pageSpaceId, delta); if ((tdbb_flags & TDBB_async) && !attachment) - dbbStat->bumpValue(type, delta); + dbbStat->bumpValue(type, pageSpaceId, delta); - // else dbbStat is adjusted from attStat, see Attachment::mergeAsyncStats() + // else dbbStat is adjusted from attStat, see Attachment::mergeStats() } - void bumpStats(const RecordStatType type, SLONG relation_id, SINT64 delta = 1) + void bumpStats(const RecordStatType type, SLONG relationId, SINT64 delta = 1) { - // We don't bump counters for dbbStat here, they're merged from attStats on demand - - reqStat->bumpValue(type, delta); - traStat->bumpValue(type, delta); - attStat->bumpValue(type, delta); - - const RuntimeStatistics* const dummyStat = RuntimeStatistics::getDummy(); - // We expect that at least attStat is present (not a dummy object) - fb_assert(attStat != dummyStat); - - // Relation statistics is a quite complex beast, so a conditional check - // does not hurt. It also allows to avoid races while accessing the static - // dummy object concurrently. + fb_assert(attStat != RuntimeStatistics::getDummy()); - if (reqStat != dummyStat) - reqStat->bumpValue(type, relation_id, delta); + reqStat->bumpValue(type, relationId, delta); + traStat->bumpValue(type, relationId, delta); + attStat->bumpValue(type, relationId, delta); - if (traStat != dummyStat) - traStat->bumpValue(type, relation_id, delta); - - if (attStat != dummyStat) - attStat->bumpValue(type, relation_id, delta); + // We don't bump counters for dbbStat here, they're merged from attStats on demand } ISC_STATUS getCancelState(ISC_STATUS* secondary = NULL); diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index ba658f45dc2..b2844c4f8a2 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -4330,7 +4330,7 @@ void TraceSweepEvent::endSweepRelation(jrd_rel* relation) fb_utils::query_performance_counter() - m_relation_clock, 0); - m_sweep_info.setPerf(stats.getPerf()); + m_sweep_info.setStats(&stats); TraceConnectionImpl conn(att); TraceManager* trace_mgr = att->att_trace_manager; @@ -4377,7 +4377,7 @@ void TraceSweepEvent::report(ntrace_process_state_t state) TraceRuntimeStats stats(att, &m_base_stats, &att->att_stats, finiTime, 0); - m_sweep_info.setPerf(stats.getPerf()); + m_sweep_info.setStats(&stats); trace_mgr->event_sweep(&conn, &m_sweep_info, state); if (state == ITracePlugin::SWEEP_STATE_FAILED || state == ITracePlugin::SWEEP_STATE_FINISHED) diff --git a/src/jrd/trace/TraceDSQLHelpers.h b/src/jrd/trace/TraceDSQLHelpers.h index 3d3f0cd78cf..1941edcac42 100644 --- a/src/jrd/trace/TraceDSQLHelpers.h +++ b/src/jrd/trace/TraceDSQLHelpers.h @@ -173,7 +173,7 @@ class TraceDSQLExecute fb_utils::query_performance_counter() - m_start_clock, m_dsqlRequest->req_fetch_rowcount); - TraceSQLStatementImpl stmt(m_dsqlRequest, stats.getPerf(), m_data); + TraceSQLStatementImpl stmt(m_dsqlRequest, &stats, m_data); TraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction, &stmt, false, result); m_dsqlRequest->req_fetch_baseline = NULL; @@ -233,7 +233,7 @@ class TraceDSQLFetch &m_dsqlRequest->getRequest()->req_stats, m_dsqlRequest->req_fetch_elapsed, m_dsqlRequest->req_fetch_rowcount); - TraceSQLStatementImpl stmt(m_dsqlRequest, stats.getPerf(), nullptr); + TraceSQLStatementImpl stmt(m_dsqlRequest, &stats, nullptr); TraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction, &stmt, false, result); diff --git a/src/jrd/trace/TraceJrdHelpers.h b/src/jrd/trace/TraceJrdHelpers.h index 2dbbfdabd97..994116042ec 100644 --- a/src/jrd/trace/TraceJrdHelpers.h +++ b/src/jrd/trace/TraceJrdHelpers.h @@ -75,7 +75,7 @@ class TraceTransactionEnd fb_utils::query_performance_counter() - m_start_clock, 0); TraceConnectionImpl conn(attachment); - TraceTransactionImpl tran(m_transaction, stats.getPerf(), m_prevID); + TraceTransactionImpl tran(m_transaction, &stats, m_prevID); attachment->att_trace_manager->event_transaction_end(&conn, &tran, m_commit, m_retain, result); m_baseline = NULL; @@ -205,7 +205,7 @@ class TraceProcExecute TraceConnectionImpl conn(attachment); TraceTransactionImpl tran(transaction); - TraceProcedureImpl proc(m_request, stats.getPerf()); + TraceProcedureImpl proc(m_request, &stats); const auto trace_mgr = attachment->att_trace_manager; trace_mgr->event_proc_execute(&conn, &tran, &proc, false, result); @@ -268,7 +268,7 @@ class TraceProcFetch TraceConnectionImpl conn(attachment); TraceTransactionImpl tran(transaction); - TraceProcedureImpl proc(m_request, stats.getPerf()); + TraceProcedureImpl proc(m_request, &stats); const auto trace_mgr = attachment->att_trace_manager; trace_mgr->event_proc_execute(&conn, &tran, &proc, false, result); @@ -402,7 +402,7 @@ class TraceFuncExecute TraceTransactionImpl tran(transaction); TraceDscFromMsg inputs(m_request->getStatement()->function->getInputFormat(), m_inMsg, m_inMsgLength); - TraceFunctionImpl func(m_request, stats.getPerf(), inputs, value); + TraceFunctionImpl func(m_request, &stats, inputs, value); const auto trace_mgr = attachment->att_trace_manager; trace_mgr->event_func_execute(&conn, &tran, &func, false, result); @@ -566,7 +566,7 @@ class TraceTrigExecute TraceConnectionImpl conn(attachment); TraceTransactionImpl tran(transaction); - TraceTriggerImpl trig(m_which, m_request, stats.getPerf()); + TraceTriggerImpl trig(m_which, m_request, &stats); const auto trace_mgr = attachment->att_trace_manager; trace_mgr->event_trigger_execute(&conn, &tran, &trig, false, result); @@ -689,7 +689,7 @@ class TraceBlrExecute TraceConnectionImpl conn(m_tdbb->getAttachment()); TraceTransactionImpl tran(m_tdbb->getTransaction()); - TraceBLRStatementImpl stmt(m_request->getStatement(), stats.getPerf()); + TraceBLRStatementImpl stmt(m_request->getStatement(), &stats); TraceManager* trace_mgr = m_tdbb->getAttachment()->att_trace_manager; trace_mgr->event_blr_execute(&conn, &tran, &stmt, result); diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 6b2d4f251df..86a503b922e 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -261,16 +261,6 @@ const char* TraceSQLStatementImpl::getTextUTF8() return m_textUTF8.c_str(); } -PerformanceInfo* TraceSQLStatementImpl::getPerf() -{ - return m_perf; -} - -ITraceParams* TraceSQLStatementImpl::getInputs() -{ - return &m_inputs; -} - /// TraceSQLStatementImpl::DSQLParamsImpl @@ -633,24 +623,62 @@ const char* TraceServiceImpl::getRemoteProcessName() /// TraceRuntimeStats -TraceRuntimeStats::TraceRuntimeStats(Attachment* att, RuntimeStatistics* baseline, RuntimeStatistics* stats, - SINT64 clock, SINT64 records_fetched) +TraceRuntimeStats::TraceRuntimeStats(Attachment* attachment, + RuntimeStatistics* baseline, RuntimeStatistics* stats, + SINT64 clock, SINT64 recordsFetched) { + memset(&m_info, 0, sizeof(m_info)); m_info.pin_time = clock * 1000 / fb_utils::query_performance_frequency(); - m_info.pin_records_fetched = records_fetched; + m_info.pin_records_fetched = recordsFetched; + m_info.pin_counters = m_globalCounters; if (baseline && stats) - baseline->computeDifference(att, *stats, m_info, m_counts, m_tempNames); + { + baseline->setToDiff(*stats); + + m_globalCounters[PerformanceInfo::FETCHES] = (*baseline)[PageStatType::FETCHES]; + m_globalCounters[PerformanceInfo::READS] = (*baseline)[PageStatType::READS]; + m_globalCounters[PerformanceInfo::MARKS] = (*baseline)[PageStatType::MARKS]; + m_globalCounters[PerformanceInfo::WRITES] = (*baseline)[PageStatType::WRITES]; + + auto getTablespaceName = [&](unsigned id) -> Firebird::string + { + return ""; // TODO + }; + + m_pageCounters.reset(&baseline->getPageCounters(), getTablespaceName); + + auto getTableName = [&](unsigned id) -> Firebird::string + { + if (attachment->att_relations && id < attachment->att_relations->count()) + { + if (const auto relation = (*attachment->att_relations)[id]) + return relation->rel_name.toQuotedString(); + } + + return ""; + }; + + m_tableCounters.reset(&baseline->getTableCounters(), getTableName); + + m_info.pin_count = m_tableCounters.getObjectCount(); + m_legacyCounts.resize(m_info.pin_count); + m_info.pin_tables = m_legacyCounts.begin(); + + for (unsigned i = 0; i < m_info.pin_count; i++) + { + m_info.pin_tables[i].trc_relation_id = m_tableCounters.getObjectId(i); + m_info.pin_tables[i].trc_relation_name = m_tableCounters.getObjectName(i); + m_info.pin_tables[i].trc_counters = m_tableCounters.getObjectCounters(i); + i++; + } + } else { - // Report all zero counts for the moment. - memset(&m_info, 0, sizeof(m_info)); - m_info.pin_counters = m_dummy_counts; + memset(m_globalCounters, 0, sizeof(m_globalCounters)); } } -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 f20cd8b0038..0aa6ec324a9 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -96,6 +96,116 @@ class StatementHolder }; +class TraceRuntimeStats : + public Firebird::AutoIface > +{ + static constexpr unsigned GLOBAL_COUNTERS = 4; // PerformanceInfo::{FETCHES|READS|MARKS|WRITES} + + template + class GenericCounters : + public Firebird::AutoIface, Firebird::CheckStatusWrapper> > + { + public: + GenericCounters() = default; + ~GenericCounters() = default; + + void reset(const T* counters, std::function getName) + { + m_counts = counters; + m_names.clear(); + + for (const auto& counts : *m_counts) + m_names.add(getName(counts.getGroupId())); + } + + // PerformanceCounts implementation + unsigned getObjectCount() + { + return m_counts ? m_counts->getCount() : 0; + } + + unsigned getCountersCapacity() + { + return T::getVectorCapacity(); + } + + unsigned getObjectId(unsigned index) + { + if (m_counts && index < m_counts->getCount()) + { + const auto iter = m_counts->begin() + index; + return iter->getGroupId(); + } + + return 0; + } + + const char* getObjectName(unsigned index) + { + if (index < m_names.getCount()) + return m_names[index].c_str(); + + return nullptr; + } + + const SINT64* getObjectCounters(unsigned index) + { + if (m_counts && index < m_counts->getCount()) + { + const auto iter = m_counts->begin() + index; + return iter->getCounterVector(); + } + + return nullptr; + } + + private: + Firebird::ObjectsArray m_names; + const T* m_counts = nullptr; + }; + + typedef GenericCounters PageCounters; + typedef GenericCounters TableCounters; + +public: + TraceRuntimeStats(Attachment* att, RuntimeStatistics* baseline, RuntimeStatistics* stats, + SINT64 clock, SINT64 recordsFetched); + + // PerformanceStats implementation + FB_UINT64 getElapsedTime() + { + return m_info.pin_time; + } + + FB_UINT64 getFetchedRecords() + { + return m_info.pin_records_fetched; + } + + Firebird::IPerformanceCounters* getPageCounters() + { + return &m_pageCounters; + } + + Firebird::IPerformanceCounters* getTableCounters() + { + return &m_tableCounters; + } + + Firebird::PerformanceInfo* getInfo() + { + return &m_info; + } + +private: + Firebird::PerformanceInfo m_info; + PageCounters m_pageCounters; + TableCounters m_tableCounters; + SINT64 m_globalCounters[GLOBAL_COUNTERS]; + Firebird::HalfStaticArray m_legacyCounts; +}; + + class TraceConnectionImpl : public Firebird::AutoIface > { @@ -127,10 +237,10 @@ class TraceTransactionImpl : public Firebird::AutoIface > { public: - TraceTransactionImpl(const jrd_tra* tran, Firebird::PerformanceInfo* perf = NULL, ISC_INT64 prevID = 0) : + TraceTransactionImpl(const jrd_tra* tran, TraceRuntimeStats* stats = nullptr, ISC_INT64 prevID = 0) : m_tran(tran), - m_perf(perf), - m_prevID(prevID) + m_prevID(prevID), + m_stats(stats) {} // TraceTransaction implementation @@ -138,14 +248,27 @@ class TraceTransactionImpl : FB_BOOLEAN getReadOnly(); int getWait(); unsigned getIsolation(); - Firebird::PerformanceInfo* getPerf() { return m_perf; } ISC_INT64 getInitialID(); - ISC_INT64 getPreviousID() { return m_prevID; } + + ISC_INT64 getPreviousID() + { + return m_prevID; + } + + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + } + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + } private: const jrd_tra* const m_tran; - Firebird::PerformanceInfo* const m_perf; const ISC_INT64 m_prevID; + TraceRuntimeStats* const m_stats; }; @@ -161,8 +284,16 @@ class BLRPrinter : {} // TraceBLRStatement implementation - const unsigned char* getData() { return m_blr; } - unsigned getDataLength() { return m_length; } + const unsigned char* getData() + { + return m_blr; + } + + unsigned getDataLength() + { + return m_length; + } + const char* getText() { if (m_text.empty() && getDataLength()) @@ -189,18 +320,30 @@ class BLRPrinter : class TraceBLRStatementImpl : public BLRPrinter { public: - TraceBLRStatementImpl(const Statement* stmt, Firebird::PerformanceInfo* perf) : + TraceBLRStatementImpl(const Statement* stmt, TraceRuntimeStats* stats) : BLRPrinter(stmt->blr.begin(), stmt->blr.getCount()), m_stmt(stmt), - m_perf(perf) + m_stats(stats) {} - ISC_INT64 getStmtID() { return m_stmt->getStatementId(); } - Firebird::PerformanceInfo* getPerf() { return m_perf; } + ISC_INT64 getStmtID() + { + return m_stmt->getStatementId(); + } + + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + } + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + } private: const Statement* const m_stmt; - Firebird::PerformanceInfo* const m_perf; + TraceRuntimeStats* const m_stats; }; @@ -211,8 +354,9 @@ class TraceFailedBLRStatement : public BLRPrinter BLRPrinter(blr, length) {} - ISC_INT64 getStmtID() { return 0; } - Firebird::PerformanceInfo* getPerf() { return NULL; } + ISC_INT64 getStmtID() { return 0; } + Firebird::PerformanceInfo* getPerf() { return nullptr; } + Firebird::IPerformanceStats* getPerfStats() { return nullptr; } }; @@ -221,20 +365,23 @@ class TraceSQLStatementImpl : public StatementHolder { public: - TraceSQLStatementImpl(DsqlRequest* stmt, Firebird::PerformanceInfo* perf, const UCHAR* inputBuffer) : + TraceSQLStatementImpl(DsqlRequest* stmt, TraceRuntimeStats* stats, const UCHAR* inputBuffer) : StatementHolder(stmt ? stmt->getStatement() : nullptr), m_stmt(stmt), - m_perf(perf), - m_inputs(stmt, inputBuffer) + m_inputs(stmt, inputBuffer), + m_stats(stats) {} // TraceSQLStatement implementation ISC_INT64 getStmtID(); - Firebird::PerformanceInfo* getPerf(); - Firebird::ITraceParams* getInputs(); const char* getText(); const char* getTextUTF8(); + Firebird::ITraceParams* getInputs() + { + return &m_inputs; + } + const char* getPlan() { return ensurePlan(false); @@ -245,6 +392,16 @@ class TraceSQLStatementImpl : return ensurePlan(true); } + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + } + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + } + private: class DSQLParamsImpl : public Firebird::AutoIface > @@ -252,8 +409,7 @@ class TraceSQLStatementImpl : public: explicit DSQLParamsImpl(DsqlRequest* const stmt, const UCHAR* const inputBuffer) : m_stmt(stmt), m_buffer(inputBuffer) - { - } + {} FB_SIZE_T getCount(); const paramdsc* getParam(FB_SIZE_T idx); @@ -269,9 +425,9 @@ class TraceSQLStatementImpl : }; DsqlRequest* const m_stmt; - Firebird::PerformanceInfo* const m_perf; DSQLParamsImpl m_inputs; Firebird::string m_textUTF8; + TraceRuntimeStats* const m_stats; }; @@ -284,13 +440,14 @@ class TraceFailedSQLStatement : {} // TraceSQLStatement implementation - ISC_INT64 getStmtID() { return 0; } - Firebird::PerformanceInfo* getPerf() { return NULL; } - Firebird::ITraceParams* getInputs() { return NULL; } - const char* getText() { return m_text.c_str(); } - const char* getPlan() { return ""; } + ISC_INT64 getStmtID() { return 0; } + Firebird::ITraceParams* getInputs() { return nullptr; } + const char* getText() { return m_text.c_str(); } + const char* getPlan() { return ""; } const char* getTextUTF8(); - const char* getExplainedPlan() { return ""; } + const char* getExplainedPlan() { return ""; } + Firebird::PerformanceInfo* getPerf() { return nullptr; } + Firebird::IPerformanceStats* getPerfStats() { return nullptr; } private: Firebird::string& m_text; @@ -444,15 +601,15 @@ class TraceProcedureImpl : TraceProcedureImpl(const Firebird::string& name, const Statement* statement) : StatementHolder(statement), m_name(name), - m_perf(nullptr), - m_inputs(nullptr, nullptr) + m_inputs(nullptr, nullptr), + m_stats(nullptr) {} - TraceProcedureImpl(Request* request, Firebird::PerformanceInfo* perf) : + TraceProcedureImpl(Request* request, TraceRuntimeStats* stats) : StatementHolder(request), m_name(getName()), - m_perf(perf), - m_inputs(request->req_proc_caller, request->req_proc_inputs) + m_inputs(request->req_proc_caller, request->req_proc_inputs), + m_stats(stats) {} // TraceProcedure implementation @@ -466,11 +623,6 @@ class TraceProcedureImpl : return m_inputs; } - Firebird::PerformanceInfo* getPerf() - { - return m_perf; - }; - ISC_INT64 getStmtID() { return getId(); @@ -486,10 +638,20 @@ class TraceProcedureImpl : return ensurePlan(true); } + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + } + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + } + private: const Firebird::string m_name; - Firebird::PerformanceInfo* const m_perf; TraceDscFromValues m_inputs; + TraceRuntimeStats* const m_stats; }; @@ -501,18 +663,18 @@ class TraceFunctionImpl : TraceFunctionImpl(const Firebird::string& name, const Statement* statement) : StatementHolder(statement), m_name(name), - m_perf(nullptr), m_inputs(nullptr), - m_value(nullptr) + m_value(nullptr), + m_stats(nullptr) {} - TraceFunctionImpl(Request* request, Firebird::PerformanceInfo* perf, + TraceFunctionImpl(Request* request, TraceRuntimeStats* stats, Firebird::ITraceParams* inputs, const dsc* value) : StatementHolder(request), m_name(getName()), - m_perf(perf), m_inputs(inputs), - m_value(value) + m_value(value), + m_stats(stats) {} // TraceFunction implementation @@ -531,11 +693,6 @@ class TraceFunctionImpl : return m_value; } - Firebird::PerformanceInfo* getPerf() - { - return m_perf; - }; - ISC_INT64 getStmtID() { return getId(); @@ -551,11 +708,21 @@ class TraceFunctionImpl : return ensurePlan(true); } + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + }; + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + }; + private: Firebird::string m_name; - Firebird::PerformanceInfo* const m_perf; Firebird::ITraceParams* const m_inputs; TraceDscFromDsc m_value; + TraceRuntimeStats* const m_stats; }; @@ -571,17 +738,17 @@ class TraceTriggerImpl : m_relationName(relationName), m_which(which), m_action(action), - m_perf(nullptr) + m_stats(nullptr) {} - TraceTriggerImpl(int which, const Request* request, Firebird::PerformanceInfo* perf) : + TraceTriggerImpl(int which, const Request* request, TraceRuntimeStats* stats) : StatementHolder(request), m_name(getName()), m_relationName((request->req_rpb.hasData() && request->req_rpb[0].rpb_relation) ? request->req_rpb[0].rpb_relation->rel_name.toQuotedString() : ""), m_which(which), m_action(request->req_trigger_action), - m_perf(perf) + m_stats(stats) {} // TraceTrigger implementation @@ -605,11 +772,6 @@ class TraceTriggerImpl : return m_action; } - Firebird::PerformanceInfo* getPerf() - { - return m_perf; - } - ISC_INT64 getStmtID() { return getId(); @@ -625,12 +787,22 @@ class TraceTriggerImpl : return ensurePlan(true); } + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + }; + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + }; + private: const Firebird::string m_name; const Firebird::string m_relationName; const int m_which; const int m_action; - Firebird::PerformanceInfo* const m_perf; + TraceRuntimeStats* const m_stats; }; @@ -662,22 +834,6 @@ class TraceServiceImpl : }; -class TraceRuntimeStats -{ -public: - TraceRuntimeStats(Attachment* att, RuntimeStatistics* baseline, RuntimeStatistics* stats, - SINT64 clock, SINT64 records_fetched); - - Firebird::PerformanceInfo* getPerf() { return &m_info; } - -private: - Firebird::PerformanceInfo m_info; - TraceCountsArray m_counts; - Firebird::ObjectsArray m_tempNames; - static SINT64 m_dummy_counts[RuntimeStatistics::GLOBAL_ITEMS]; // Zero-initialized array with zero counts -}; - - class TraceInitInfoImpl : public Firebird::AutoIface > { @@ -759,14 +915,7 @@ class TraceSweepImpl : public Firebird::AutoIface > { public: - TraceSweepImpl() - { - m_oit = 0; - m_ost = 0; - m_oat = 0; - m_next = 0; - m_perf = 0; - } + TraceSweepImpl() = default; void update(const Ods::header_page* header) { @@ -776,23 +925,32 @@ class TraceSweepImpl : m_next = header->hdr_next_transaction; } - void setPerf(Firebird::PerformanceInfo* perf) + void setStats(TraceRuntimeStats* stats) { - m_perf = perf; + m_stats = stats; } ISC_INT64 getOIT() { return m_oit; }; ISC_INT64 getOST() { return m_ost; }; ISC_INT64 getOAT() { return m_oat; }; ISC_INT64 getNext() { return m_next; }; - Firebird::PerformanceInfo* getPerf() { return m_perf; }; + + Firebird::PerformanceInfo* getPerf() + { + return m_stats ? m_stats->getInfo() : nullptr; + }; + + Firebird::IPerformanceStats* getPerfStats() + { + return m_stats; + }; private: - TraNumber m_oit; - TraNumber m_ost; - TraNumber m_oat; - TraNumber m_next; - Firebird::PerformanceInfo* m_perf; + TraNumber m_oit = 0; + TraNumber m_ost = 0; + TraNumber m_oat = 0; + TraNumber m_next = 0; + TraceRuntimeStats* m_stats = nullptr; }; } // namespace Jrd diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index a962af94748..8d0a49d2b59 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -629,56 +629,73 @@ void TracePluginImpl::logRecordError(const char* action, ITraceConnection* conne logRecord(action); } -void TracePluginImpl::appendGlobalCounts(const PerformanceInfo* info) +void TracePluginImpl::appendGlobalCounts(IPerformanceStats* stats) { string temp; - temp.printf("%7" QUADFORMAT"d ms", info->pin_time); + temp.printf("%7" QUADFORMAT"d ms", stats->getElapsedTime()); record.append(temp); - ntrace_counter_t cnt; + const auto pageCounters = stats->getPageCounters(); - if ((cnt = info->pin_counters[PerformanceInfo::READS]) != 0) + if (const auto count = pageCounters->getObjectCount()) { - temp.printf(", %" QUADFORMAT"d read(s)", cnt); - record.append(temp); - } + // Holds counters: IPerformanceCounters::PAGE_{FETCHES|READS|MARKS|WRITES} + static constexpr unsigned GLOBAL_COUNTERS = 4; + SINT64 globalCounters[GLOBAL_COUNTERS] = {0}; - if ((cnt = info->pin_counters[PerformanceInfo::WRITES]) != 0) - { - temp.printf(", %" QUADFORMAT"d write(s)", cnt); - record.append(temp); - } + for (unsigned i = 0; i < count; i++) + { + const auto counters = pageCounters->getObjectCounters(i); + for (unsigned j = 0; j < GLOBAL_COUNTERS; j++) + globalCounters[j] += counters[j]; + } - if ((cnt = info->pin_counters[PerformanceInfo::FETCHES]) != 0) - { - temp.printf(", %" QUADFORMAT"d fetch(es)", cnt); - record.append(temp); - } + if (const auto cnt = globalCounters[IPerformanceCounters::PAGE_READS]) + { + temp.printf(", %" QUADFORMAT"d read(s)", cnt); + record.append(temp); + } - if ((cnt = info->pin_counters[PerformanceInfo::MARKS]) != 0) - { - temp.printf(", %" QUADFORMAT"d mark(s)", cnt); - record.append(temp); + if (const auto cnt = globalCounters[IPerformanceCounters::PAGE_WRITES]) + { + temp.printf(", %" QUADFORMAT"d write(s)", cnt); + record.append(temp); + } + + if (const auto cnt = globalCounters[IPerformanceCounters::PAGE_FETCHES]) + { + temp.printf(", %" QUADFORMAT"d fetch(es)", cnt); + record.append(temp); + } + + if (const auto cnt = globalCounters[IPerformanceCounters::PAGE_MARKS]) + { + temp.printf(", %" QUADFORMAT"d mark(s)", cnt); + record.append(temp); + } } record.append(NEWLINE); } -void TracePluginImpl::appendTableCounts(const PerformanceInfo *info) +void TracePluginImpl::appendTableCounts(IPerformanceStats* stats) { - if (!config.print_perf || info->pin_count == 0) - return; + const auto tableCounters = stats->getTableCounters(); + const auto count = tableCounters->getObjectCount(); - const TraceCounts* trc = info->pin_tables; - const TraceCounts* trc_end = trc + info->pin_count; + if (!config.print_perf || !count) + return; FB_SIZE_T max_len = 0; - for (; trc < trc_end; trc++) + for (unsigned i = 0; i < count; i++) { - FB_SIZE_T len = fb_strlen(trc->trc_relation_name); - if (max_len < len) - max_len = len; + if (const auto relName = tableCounters->getObjectName(i)) + { + const FB_SIZE_T len = fb_strlen(relName); + if (max_len < len) + max_len = len; + } } if (max_len < 32) @@ -691,24 +708,45 @@ void TracePluginImpl::appendTableCounts(const PerformanceInfo *info) record.append(NEWLINE); string temp; - for (trc = info->pin_tables; trc < trc_end; trc++) + for (unsigned i = 0; i < count; i++) { - record.append(trc->trc_relation_name); - record.append(max_len - fb_strlen(trc->trc_relation_name), ' '); - for (int j = 0; j <= TraceCounts::EXPUNGES; j++) + const auto relName = tableCounters->getObjectName(i); + if (relName && *relName) + { + record.append(relName); + record.append(max_len - fb_strlen(relName), ' '); + } + else + { + temp.printf("Table id <%u>", tableCounters->getObjectId(i)); + record.append(temp); + record.append(max_len - temp.length(), ' '); + } + + const auto counters = tableCounters->getObjectCounters(i); + + string line; + bool nonZero = false; + for (unsigned j = IPerformanceCounters::RECORD_SEQ_READS; + j <= IPerformanceCounters::RECORD_EXPUNGES; j++) { - if (trc->trc_counters[j] == 0) + if (counters[j] == 0) { - record.append(10, ' '); + line.append(10, ' '); } else { - //fb_utils::exactNumericToStr(trc->trc_counters[j], 0, temp); + //fb_utils::exactNumericToStr(counterVector[j], 0, temp); //record.append(' ', 10 - temp.length()); - temp.printf("%10" QUADFORMAT"d", trc->trc_counters[j]); - record.append(temp); + temp.printf("%10" QUADFORMAT"d", counters[j]); + line.append(temp); + nonZero = true; } } + + if (nonZero) + record.append(line); + record.append(NEWLINE); } } @@ -1494,11 +1532,10 @@ void TracePluginImpl::log_event_transaction_end(ITraceDatabaseConnection* connec } } - PerformanceInfo* info = transaction->getPerf(); - if (info) + if (const auto stats = transaction->getPerfStats()) { - appendGlobalCounts(info); - appendTableCounts(info); + appendGlobalCounts(stats); + appendTableCounts(stats); } const char* event_type; @@ -1596,8 +1633,8 @@ void TracePluginImpl::log_event_proc_execute(ITraceDatabaseConnection* connectio return; // Do not log operation if it is below time threshold - const PerformanceInfo* info = started ? NULL : procedure->getPerf(); - if (config.time_threshold && info && info->pin_time < config.time_threshold) + IPerformanceStats* const stats = started ? nullptr : procedure->getPerfStats(); + if (config.time_threshold && stats && stats->getElapsedTime() < config.time_threshold) return; ITraceParams* params = procedure->getInputs(); @@ -1608,16 +1645,17 @@ void TracePluginImpl::log_event_proc_execute(ITraceDatabaseConnection* connectio record.append(NEWLINE); } - if (info) + if (stats) { - if (info->pin_records_fetched) + if (const auto cnt = stats->getFetchedRecords()) { string temp; - temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, info->pin_records_fetched); + temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, cnt); record.append(temp); } - appendGlobalCounts(info); - appendTableCounts(info); + + appendGlobalCounts(stats); + appendTableCounts(stats); } const char* event_type; @@ -1677,8 +1715,8 @@ void TracePluginImpl::log_event_func_execute(ITraceDatabaseConnection* connectio return; // Do not log operation if it is below time threshold - const PerformanceInfo* info = started ? NULL : function->getPerf(); - if (config.time_threshold && info && info->pin_time < config.time_threshold) + IPerformanceStats* const stats = started ? nullptr : function->getPerfStats(); + if (config.time_threshold && stats && stats->getElapsedTime() < config.time_threshold) return; ITraceParams* params = function->getInputs(); @@ -1699,16 +1737,17 @@ void TracePluginImpl::log_event_func_execute(ITraceDatabaseConnection* connectio } } - if (info) + if (stats) { - if (info->pin_records_fetched) + if (const auto cnt = stats->getFetchedRecords()) { string temp; - temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, info->pin_records_fetched); + temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, cnt); record.append(temp); } - appendGlobalCounts(info); - appendTableCounts(info); + + appendGlobalCounts(stats); + appendTableCounts(stats); } const char* event_type; @@ -1767,14 +1806,14 @@ void TracePluginImpl::log_event_trigger_execute(ITraceDatabaseConnection* connec return; // Do not log operation if it is below time threshold - const PerformanceInfo* info = started ? NULL : trigger->getPerf(); - if (config.time_threshold && info && info->pin_time < config.time_threshold) + IPerformanceStats* const stats = started ? nullptr : trigger->getPerfStats(); + if (config.time_threshold && stats && stats->getElapsedTime() < config.time_threshold) return; - if (info) + if (stats) { - appendGlobalCounts(info); - appendTableCounts(info); + appendGlobalCounts(stats); + appendTableCounts(stats); } const char* event_type; @@ -1920,8 +1959,8 @@ void TracePluginImpl::log_event_dsql_execute(ITraceDatabaseConnection* connectio return; // Do not log operation if it is below time threshold - const PerformanceInfo* info = started ? NULL : statement->getPerf(); - if (config.time_threshold && info && info->pin_time < config.time_threshold) + IPerformanceStats* const stats = started ? nullptr : statement->getPerfStats(); + if (config.time_threshold && stats && stats->getElapsedTime() < config.time_threshold) return; if (restart) @@ -1939,14 +1978,14 @@ void TracePluginImpl::log_event_dsql_execute(ITraceDatabaseConnection* connectio record.append(NEWLINE); } - if (info) + if (stats) { string temp; - temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, info->pin_records_fetched); + temp.printf("%" QUADFORMAT"d records fetched" NEWLINE, stats->getFetchedRecords()); record.append(temp); - appendGlobalCounts(info); - appendTableCounts(info); + appendGlobalCounts(stats); + appendTableCounts(stats); } string event_type; @@ -2058,16 +2097,19 @@ void TracePluginImpl::log_event_blr_execute(ITraceDatabaseConnection* connection ITraceTransaction* transaction, ITraceBLRStatement* statement, ntrace_result_t req_result) { - PerformanceInfo *info = statement->getPerf(); + const auto stats = statement->getPerfStats(); // Do not log operation if it is below time threshold - if (config.time_threshold && info->pin_time < config.time_threshold) + if (config.time_threshold && stats && stats->getElapsedTime() < config.time_threshold) return; if (config.log_blr_requests) { - appendGlobalCounts(info); - appendTableCounts(info); + if (stats) + { + appendGlobalCounts(stats); + appendTableCounts(stats); + } const char* event_type; switch (req_result) @@ -2440,11 +2482,10 @@ void TracePluginImpl::log_event_sweep(ITraceDatabaseConnection* connection, ITra ); } - PerformanceInfo* info = sweep->getPerf(); - if (info) + if (const auto stats = sweep->getPerfStats()) { - appendGlobalCounts(info); - appendTableCounts(info); + appendGlobalCounts(stats); + appendTableCounts(stats); } const char* event_type = NULL; diff --git a/src/utilities/ntrace/TracePluginImpl.h b/src/utilities/ntrace/TracePluginImpl.h index e84330599b1..4025af881ff 100644 --- a/src/utilities/ntrace/TracePluginImpl.h +++ b/src/utilities/ntrace/TracePluginImpl.h @@ -178,8 +178,8 @@ class TracePluginImpl final : GdsCodesArray include_codes; GdsCodesArray exclude_codes; - void appendGlobalCounts(const Firebird::PerformanceInfo* info); - void appendTableCounts(const Firebird::PerformanceInfo* info); + void appendGlobalCounts(Firebird::IPerformanceStats* stats); + void appendTableCounts(Firebird::IPerformanceStats* stats); void appendParams(Firebird::ITraceParams* params); void appendServiceQueryParams(size_t send_item_length, const ntrace_byte_t* send_items, size_t recv_item_length, const ntrace_byte_t* recv_items);