8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 05:23:03 +01:00

This should fix the races while accessing the relation statistics inside dbb_stats. Reads/writes/fetches/marks are incremented (CCH) and read (INF) unprotected, as it's crash safe and read skews are acceptable. Other counters (both global and relation wise) are protected with a mutex. They're incremented on demand based on the attachment counters (via diffs). While being there, cleaned up the currently unused performance counters.

This commit is contained in:
dimitr 2016-01-24 21:14:18 +00:00
parent dd738c7f80
commit 99ad42ab82
12 changed files with 54 additions and 37 deletions

View File

@ -179,6 +179,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
att_lock_owner_id(Database::getLockOwnerId()),
att_backup_state_counter(0),
att_stats(*pool),
att_base_stats(*pool),
att_working_directory(*pool),
att_filename(*pool),
att_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()),
@ -381,6 +382,14 @@ void Jrd::Attachment::signalShutdown()
}
void Jrd::Attachment::mergeStats()
{
MutexLockGuard guard(att_database->dbb_stats_mutex, FB_FUNCTION);
att_database->dbb_stats.adjust(att_base_stats, att_stats, true);
att_base_stats.assign(att_stats);
}
// Find an inactive incarnation of a system request. If necessary, clone it.
jrd_req* Jrd::Attachment::findSystemRequest(thread_db* tdbb, USHORT id, USHORT which)
{

View File

@ -250,6 +250,7 @@ public:
SecurityClass* att_security_class; // security class for database
SecurityClassList* att_security_classes; // security classes
RuntimeStatistics att_stats;
RuntimeStatistics att_base_stats;
ULONG att_flags; // Flags describing the state of the attachment
SSHORT att_client_charset; // user's charset specified in dpb
SSHORT att_charset; // current (client or external) attachment charset
@ -355,6 +356,8 @@ public:
void signalCancel();
void signalShutdown();
void mergeStats();
bool backupStateWriteLock(thread_db* tdbb, SSHORT wait);
void backupStateWriteUnLock(thread_db* tdbb);
bool backupStateReadLock(thread_db* tdbb, SSHORT wait);

View File

@ -447,8 +447,9 @@ public:
Firebird::Semaphore dbb_gc_fini; // Event for finalization garbage collector
Firebird::MemoryStats dbb_memory_stats;
RuntimeStatistics dbb_stats;
mutable Firebird::Mutex dbb_stats_mutex;
TraNumber dbb_last_header_write; // Transaction id of last header page physical write
SLONG dbb_flush_cycle; // Current flush cycle
ULONG dbb_sweep_interval; // Transactions between sweep

View File

@ -281,8 +281,6 @@ JrdStatement* JrdStatement::makeStatement(thread_db* tdbb, CompilerScratch* csb,
if (internalFlag)
statement->flags |= FLAG_INTERNAL;
else
tdbb->bumpStats(RuntimeStatistics::STMT_PREPARES);
return statement;
}

View File

@ -786,6 +786,7 @@ void Monitoring::putDatabase(SnapshotData::DumpRecord& record, const Database* d
if (database->dbb_flags & DBB_shared)
{
MutexLockGuard guard(database->dbb_stats_mutex, FB_FUNCTION);
putStatistics(record, database->dbb_stats, writer, stat_id, stat_database);
putMemoryUsage(record, database->dbb_memory_stats, writer, stat_id, stat_database);
}
@ -876,6 +877,7 @@ void Monitoring::putAttachment(SnapshotData::DumpRecord& record, const Jrd::Atta
}
else
{
MutexLockGuard guard(attachment->att_database->dbb_stats_mutex, FB_FUNCTION);
putStatistics(record, attachment->att_database->dbb_stats, writer, stat_id, stat_attachment);
putMemoryUsage(record, attachment->att_database->dbb_memory_stats, writer, stat_id, stat_attachment);
}
@ -1182,7 +1184,7 @@ void Monitoring::checkState(thread_db* tdbb)
}
void Monitoring::dumpAttachment(thread_db* tdbb, const Attachment* attachment, bool ast)
void Monitoring::dumpAttachment(thread_db* tdbb, Attachment* attachment, bool ast)
{
if (!attachment->att_user)
return;
@ -1190,6 +1192,8 @@ void Monitoring::dumpAttachment(thread_db* tdbb, const Attachment* attachment, b
Database* const dbb = tdbb->getDatabase();
MemoryPool& pool = *dbb->dbb_permanent;
attachment->mergeStats();
const AttNumber att_id = attachment->att_attachment_id;
const string& user_name = attachment->att_user->usr_user_name;

View File

@ -385,7 +385,7 @@ public:
static void checkState(thread_db* tdbb);
static SnapshotData* getSnapshot(thread_db* tdbb);
static void dumpAttachment(thread_db* tdbb, const Attachment* attachment, bool ast);
static void dumpAttachment(thread_db* tdbb, Attachment* attachment, bool ast);
static void publishAttachment(thread_db* tdbb);
static void cleanupAttachment(thread_db* tdbb);

View File

@ -50,7 +50,6 @@ public:
PAGE_READS,
PAGE_MARKS,
PAGE_WRITES,
FLUSHES,
RECORD_SEQ_READS,
RECORD_IDX_READS,
RECORD_UPDATES,
@ -65,23 +64,18 @@ public:
RECORD_BACKVERSION_READS,
RECORD_FRAGMENT_READS,
RECORD_RPT_READS,
SORTS,
SORT_GETS,
SORT_PUTS,
STMT_PREPARES,
STMT_EXECUTES,
TOTAL_ITEMS // last
};
private:
static const size_t REL_BASE_OFFSET = RECORD_SEQ_READS;
static const size_t REL_TOTAL_ITEMS = RECORD_RPT_READS - REL_BASE_OFFSET + 1;
// Performance counters for individual table
class RelationCounts
{
static const size_t REL_BASE_OFFSET = RECORD_SEQ_READS;
public:
static const size_t REL_TOTAL_ITEMS = RECORD_RPT_READS - REL_BASE_OFFSET + 1;
explicit RelationCounts(SLONG relation_id)
: rlc_relation_id(relation_id)
{
@ -158,6 +152,7 @@ public:
typedef Firebird::SortedArray<RelationCounts, Firebird::EmptyStorage<RelationCounts>,
SLONG, RelationCounts> RelCounters;
public:
RuntimeStatistics()
: Firebird::AutoStorage(), rel_counts(getPool())
{
@ -226,12 +221,14 @@ public:
// add difference between newStats and baseStats to our counters
// newStats and baseStats must be "in-sync"
void adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats)
void adjust(const RuntimeStatistics& baseStats, const RuntimeStatistics& newStats, bool relStatsOnly = false)
{
if (baseStats.allChgNumber != newStats.allChgNumber)
{
const size_t FIRST_ITEM = relStatsOnly ? REL_BASE_OFFSET : 0;
allChgNumber++;
for (size_t i = 0; i < TOTAL_ITEMS; ++i)
for (size_t i = FIRST_ITEM; i < TOTAL_ITEMS; ++i)
values[i] += newStats.values[i] - baseStats.values[i];
if (baseStats.relChgNumber != newStats.relChgNumber)

View File

@ -1037,8 +1037,6 @@ void CCH_flush(thread_db* tdbb, USHORT flush_flag, TraNumber tra_number)
if (backup_state == Ods::hdr_nbak_stalled || backup_state == Ods::hdr_nbak_merge)
bm->flushDifference(tdbb);
}
tdbb->bumpStats(RuntimeStatistics::FLUSHES);
}
// take the opportunity when we know there are no pages

View File

@ -902,9 +902,6 @@ void EXE_start(thread_db* tdbb, jrd_req* request, jrd_tra* transaction)
impure->vlu_flags = 0;
}
if (statement->sqlText)
tdbb->bumpStats(RuntimeStatistics::STMT_EXECUTES);
request->req_src_line = 0;
request->req_src_column = 0;

View File

@ -6358,6 +6358,8 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
attachment->deletePool(pool);
}
attachment->mergeStats();
// remove the attachment block from the dbb linked list
Sync sync(&dbb->dbb_sync, "jrd.cpp: release_attachment");
sync.lock(SYNC_EXCLUSIVE);
@ -7399,17 +7401,13 @@ void thread_db::setDatabase(Database* val)
const bool wasActive = database && (priorThread || nextThread || database->dbb_active_threads == this);
if (wasActive)
{
deactivate();
}
database = val;
dbbStat = val ? &val->dbb_stats : RuntimeStatistics::getDummy();
if (wasActive)
{
activate();
}
}
}

View File

@ -459,12 +459,30 @@ public:
void bumpRelStats(const RuntimeStatistics::StatType index, SLONG relation_id, SINT64 delta = 1)
{
bumpStats(index, delta);
// We don't bump counters for dbbStat here, they're merged from attStats on demand
reqStat->bumpRelValue(index, relation_id, delta);
traStat->bumpRelValue(index, relation_id, delta);
attStat->bumpRelValue(index, relation_id, delta);
dbbStat->bumpRelValue(index, relation_id, delta);
reqStat->bumpValue(index, delta);
traStat->bumpValue(index, delta);
attStat->bumpValue(index, 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.
if (reqStat != dummyStat)
reqStat->bumpRelValue(index, relation_id, delta);
if (traStat != dummyStat)
traStat->bumpRelValue(index, relation_id, delta);
if (attStat != dummyStat)
attStat->bumpRelValue(index, relation_id, delta);
}
ISC_STATUS checkCancelState();

View File

@ -342,8 +342,6 @@ void Sort::get(thread_db* tdbb, ULONG** record_address)
{
diddleKey((UCHAR*) record->sort_record_key, false);
}
tdbb->bumpStats(RuntimeStatistics::SORT_GETS);
}
catch (const BadAlloc&)
{
@ -419,8 +417,6 @@ void Sort::put(thread_db* tdbb, ULONG** record_address)
*m_next_pointer++ = reinterpret_cast<sort_record*>(record->sr_sort_record.sort_record_key);
m_records++;
*record_address = (ULONG*) record->sr_sort_record.sort_record_key;
tdbb->bumpStats(RuntimeStatistics::SORT_PUTS);
}
catch (const BadAlloc&)
{
@ -463,7 +459,6 @@ void Sort::sort(thread_db* tdbb)
sort();
m_next_pointer = m_first_pointer + 1;
m_flags |= scb_sorted;
tdbb->bumpStats(RuntimeStatistics::SORTS);
return;
}
@ -619,7 +614,6 @@ void Sort::sort(thread_db* tdbb)
sortRunsBySeek(run_count);
m_flags |= scb_sorted;
tdbb->bumpStats(RuntimeStatistics::SORTS);
}
catch (const BadAlloc&)
{