macros for perf_context

Summary: This will allow us to disable them completely for iOS or for better performance

Test Plan: will run make all check

Reviewers: igor, haobo, dhruba

Reviewed By: haobo

CC: leveldb

Differential Revision: https://reviews.facebook.net/D17511
This commit is contained in:
Lei Jin 2014-04-08 10:58:07 -07:00
parent 5abae2c8ed
commit 92c1eb0291
11 changed files with 139 additions and 105 deletions

View file

@ -3331,8 +3331,7 @@ Status DBImpl::GetImpl(const ReadOptions& options,
ColumnFamilyHandle* column_family, const Slice& key, ColumnFamilyHandle* column_family, const Slice& key,
std::string* value, bool* value_found) { std::string* value, bool* value_found) {
StopWatch sw(env_, options_.statistics.get(), DB_GET, false); StopWatch sw(env_, options_.statistics.get(), DB_GET, false);
StopWatchNano snapshot_timer(env_, false); PERF_TIMER_AUTO(get_snapshot_time);
StartPerfTimer(&snapshot_timer);
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family); auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
auto cfd = cfh->cfd(); auto cfd = cfh->cfd();
@ -3404,7 +3403,7 @@ Status DBImpl::GetImpl(const ReadOptions& options,
// s is both in/out. When in, s could either be OK or MergeInProgress. // s is both in/out. When in, s could either be OK or MergeInProgress.
// merge_operands will contain the sequence of merges in the latter case. // merge_operands will contain the sequence of merges in the latter case.
LookupKey lkey(key, snapshot); LookupKey lkey(key, snapshot);
BumpPerfTime(&perf_context.get_snapshot_time, &snapshot_timer); PERF_TIMER_STOP(get_snapshot_time);
if (sv->mem->Get(lkey, value, &s, merge_context, *cfd->options())) { if (sv->mem->Get(lkey, value, &s, merge_context, *cfd->options())) {
// Done // Done
RecordTick(options_.statistics.get(), MEMTABLE_HIT); RecordTick(options_.statistics.get(), MEMTABLE_HIT);
@ -3412,18 +3411,16 @@ Status DBImpl::GetImpl(const ReadOptions& options,
// Done // Done
RecordTick(options_.statistics.get(), MEMTABLE_HIT); RecordTick(options_.statistics.get(), MEMTABLE_HIT);
} else { } else {
StopWatchNano from_files_timer(env_, false); PERF_TIMER_START(get_from_output_files_time);
StartPerfTimer(&from_files_timer);
sv->current->Get(options, lkey, value, &s, &merge_context, &stats, sv->current->Get(options, lkey, value, &s, &merge_context, &stats,
*cfd->options(), value_found); *cfd->options(), value_found);
have_stat_update = true; have_stat_update = true;
BumpPerfTime(&perf_context.get_from_output_files_time, &from_files_timer); PERF_TIMER_STOP(get_from_output_files_time);
RecordTick(options_.statistics.get(), MEMTABLE_MISS); RecordTick(options_.statistics.get(), MEMTABLE_MISS);
} }
StopWatchNano post_process_timer(env_, false); PERF_TIMER_START(get_post_process_time);
StartPerfTimer(&post_process_timer);
if (!cfd->options()->disable_seek_compaction && have_stat_update) { if (!cfd->options()->disable_seek_compaction && have_stat_update) {
mutex_.Lock(); mutex_.Lock();
@ -3464,7 +3461,7 @@ Status DBImpl::GetImpl(const ReadOptions& options,
RecordTick(options_.statistics.get(), NUMBER_KEYS_READ); RecordTick(options_.statistics.get(), NUMBER_KEYS_READ);
RecordTick(options_.statistics.get(), BYTES_READ, value->size()); RecordTick(options_.statistics.get(), BYTES_READ, value->size());
BumpPerfTime(&perf_context.get_post_process_time, &post_process_timer); PERF_TIMER_STOP(get_post_process_time);
return s; return s;
} }
@ -3474,8 +3471,7 @@ std::vector<Status> DBImpl::MultiGet(
const std::vector<Slice>& keys, std::vector<std::string>* values) { const std::vector<Slice>& keys, std::vector<std::string>* values) {
StopWatch sw(env_, options_.statistics.get(), DB_MULTIGET, false); StopWatch sw(env_, options_.statistics.get(), DB_MULTIGET, false);
StopWatchNano snapshot_timer(env_, false); PERF_TIMER_AUTO(get_snapshot_time);
StartPerfTimer(&snapshot_timer);
SequenceNumber snapshot; SequenceNumber snapshot;
@ -3519,7 +3515,7 @@ std::vector<Status> DBImpl::MultiGet(
// Keep track of bytes that we read for statistics-recording later // Keep track of bytes that we read for statistics-recording later
uint64_t bytes_read = 0; uint64_t bytes_read = 0;
BumpPerfTime(&perf_context.get_snapshot_time, &snapshot_timer); PERF_TIMER_STOP(get_snapshot_time);
// For each of the given keys, apply the entire "get" process as follows: // For each of the given keys, apply the entire "get" process as follows:
// First look in the memtable, then in the immutable memtable (if any). // First look in the memtable, then in the immutable memtable (if any).
@ -3555,8 +3551,7 @@ std::vector<Status> DBImpl::MultiGet(
} }
// Post processing (decrement reference counts and record statistics) // Post processing (decrement reference counts and record statistics)
StopWatchNano post_process_timer(env_, false); PERF_TIMER_START(get_post_process_time);
StartPerfTimer(&post_process_timer);
autovector<SuperVersion*> superversions_to_delete; autovector<SuperVersion*> superversions_to_delete;
bool schedule_flush_or_compaction = false; bool schedule_flush_or_compaction = false;
@ -3589,7 +3584,7 @@ std::vector<Status> DBImpl::MultiGet(
RecordTick(options_.statistics.get(), NUMBER_MULTIGET_CALLS); RecordTick(options_.statistics.get(), NUMBER_MULTIGET_CALLS);
RecordTick(options_.statistics.get(), NUMBER_MULTIGET_KEYS_READ, num_keys); RecordTick(options_.statistics.get(), NUMBER_MULTIGET_KEYS_READ, num_keys);
RecordTick(options_.statistics.get(), NUMBER_MULTIGET_BYTES_READ, bytes_read); RecordTick(options_.statistics.get(), NUMBER_MULTIGET_BYTES_READ, bytes_read);
BumpPerfTime(&perf_context.get_post_process_time, &post_process_timer); PERF_TIMER_STOP(get_post_process_time);
return stat_list; return stat_list;
} }
@ -3803,8 +3798,7 @@ Status DBImpl::Delete(const WriteOptions& options,
} }
Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) { Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
StopWatchNano pre_post_process_timer(env_, false); PERF_TIMER_AUTO(write_pre_and_post_process_time);
StartPerfTimer(&pre_post_process_timer);
Writer w(&mutex_); Writer w(&mutex_);
w.batch = my_batch; w.batch = my_batch;
w.sync = options.sync; w.sync = options.sync;
@ -3883,12 +3877,10 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
if (options.disableWAL) { if (options.disableWAL) {
flush_on_destroy_ = true; flush_on_destroy_ = true;
} }
BumpPerfTime(&perf_context.write_pre_and_post_process_time, PERF_TIMER_STOP(write_pre_and_post_process_time);
&pre_post_process_timer);
if (!options.disableWAL) { if (!options.disableWAL) {
StopWatchNano timer(env_); PERF_TIMER_START(write_wal_time);
StartPerfTimer(&timer);
Slice log_entry = WriteBatchInternal::Contents(updates); Slice log_entry = WriteBatchInternal::Contents(updates);
status = log_->AddRecord(log_entry); status = log_->AddRecord(log_entry);
RecordTick(options_.statistics.get(), WAL_FILE_SYNCED, 1); RecordTick(options_.statistics.get(), WAL_FILE_SYNCED, 1);
@ -3902,15 +3894,13 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
status = log_->file()->Sync(); status = log_->file()->Sync();
} }
} }
BumpPerfTime(&perf_context.write_wal_time, &timer); PERF_TIMER_STOP(write_wal_time);
} }
if (status.ok()) { if (status.ok()) {
StopWatchNano write_memtable_timer(env_, false); PERF_TIMER_START(write_memtable_time);
StartPerfTimer(&write_memtable_timer);
status = WriteBatchInternal::InsertInto( status = WriteBatchInternal::InsertInto(
updates, column_family_memtables_.get(), false, 0, this, false); updates, column_family_memtables_.get(), false, 0, this, false);
BumpPerfTime(&perf_context.write_memtable_time, &write_memtable_timer); PERF_TIMER_STOP(write_memtable_time);
if (!status.ok()) { if (!status.ok()) {
// Iteration failed (either in-memory writebatch corruption (very // Iteration failed (either in-memory writebatch corruption (very
@ -3924,7 +3914,7 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
SetTickerCount(options_.statistics.get(), SEQUENCE_NUMBER, SetTickerCount(options_.statistics.get(), SEQUENCE_NUMBER,
last_sequence); last_sequence);
} }
StartPerfTimer(&pre_post_process_timer); PERF_TIMER_START(write_pre_and_post_process_time);
if (updates == &tmp_batch_) tmp_batch_.Clear(); if (updates == &tmp_batch_) tmp_batch_.Clear();
mutex_.Lock(); mutex_.Lock();
if (status.ok()) { if (status.ok()) {
@ -3952,8 +3942,7 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
writers_.front()->cv.Signal(); writers_.front()->cv.Signal();
} }
mutex_.Unlock(); mutex_.Unlock();
BumpPerfTime(&perf_context.write_pre_and_post_process_time, PERF_TIMER_STOP(write_pre_and_post_process_time);
&pre_post_process_timer);
return status; return status;
} }

View file

@ -189,10 +189,9 @@ void DBIter::Next() {
// NOTE: In between, saved_key_ can point to a user key that has // NOTE: In between, saved_key_ can point to a user key that has
// a delete marker // a delete marker
inline void DBIter::FindNextUserEntry(bool skipping) { inline void DBIter::FindNextUserEntry(bool skipping) {
StopWatchNano timer(env_, false); PERF_TIMER_AUTO(find_next_user_entry_time);
StartPerfTimer(&timer);
FindNextUserEntryInternal(skipping); FindNextUserEntryInternal(skipping);
BumpPerfTime(&perf_context.find_next_user_entry_time, &timer); PERF_TIMER_STOP(find_next_user_entry_time);
} }
// Actual implementation of DBIter::FindNextUserEntry() // Actual implementation of DBIter::FindNextUserEntry()
@ -208,7 +207,7 @@ void DBIter::FindNextUserEntryInternal(bool skipping) {
if (skipping && if (skipping &&
user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) { user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) {
num_skipped++; // skip this entry num_skipped++; // skip this entry
BumpPerfCount(&perf_context.internal_key_skipped_count); PERF_COUNTER_ADD(internal_key_skipped_count, 1);
} else { } else {
skipping = false; skipping = false;
switch (ikey.type) { switch (ikey.type) {
@ -218,7 +217,7 @@ void DBIter::FindNextUserEntryInternal(bool skipping) {
saved_key_.SetUserKey(ikey.user_key); saved_key_.SetUserKey(ikey.user_key);
skipping = true; skipping = true;
num_skipped = 0; num_skipped = 0;
BumpPerfCount(&perf_context.internal_delete_skipped_count); PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
break; break;
case kTypeValue: case kTypeValue:
valid_ = true; valid_ = true;
@ -423,10 +422,9 @@ void DBIter::Seek(const Slice& target) {
saved_key_.Clear(); saved_key_.Clear();
// now savved_key is used to store internal key. // now savved_key is used to store internal key.
saved_key_.SetInternalKey(target, sequence_); saved_key_.SetInternalKey(target, sequence_);
StopWatchNano internal_seek_timer(env_, false); PERF_TIMER_AUTO(seek_internal_seek_time);
StartPerfTimer(&internal_seek_timer);
iter_->Seek(saved_key_.GetKey()); iter_->Seek(saved_key_.GetKey());
BumpPerfTime(&perf_context.seek_internal_seek_time, &internal_seek_timer); PERF_TIMER_STOP(seek_internal_seek_time);
if (iter_->Valid()) { if (iter_->Valid()) {
direction_ = kForward; direction_ = kForward;
ClearSavedValue(); ClearSavedValue();
@ -439,10 +437,9 @@ void DBIter::Seek(const Slice& target) {
void DBIter::SeekToFirst() { void DBIter::SeekToFirst() {
direction_ = kForward; direction_ = kForward;
ClearSavedValue(); ClearSavedValue();
StopWatchNano internal_seek_timer(env_, false); PERF_TIMER_AUTO(seek_internal_seek_time);
StartPerfTimer(&internal_seek_timer);
iter_->SeekToFirst(); iter_->SeekToFirst();
BumpPerfTime(&perf_context.seek_internal_seek_time, &internal_seek_timer); PERF_TIMER_STOP(seek_internal_seek_time);
if (iter_->Valid()) { if (iter_->Valid()) {
FindNextUserEntry(false /* not skipping */); FindNextUserEntry(false /* not skipping */);
} else { } else {
@ -461,10 +458,9 @@ void DBIter::SeekToLast() {
direction_ = kReverse; direction_ = kReverse;
ClearSavedValue(); ClearSavedValue();
StopWatchNano internal_seek_timer(env_, false); PERF_TIMER_AUTO(seek_internal_seek_time);
StartPerfTimer(&internal_seek_timer);
iter_->SeekToLast(); iter_->SeekToLast();
BumpPerfTime(&perf_context.seek_internal_seek_time, &internal_seek_timer); PERF_TIMER_STOP(seek_internal_seek_time);
FindPrevUserEntry(); FindPrevUserEntry();
} }

View file

@ -59,7 +59,7 @@ int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const {
// decreasing sequence number // decreasing sequence number
// decreasing type (though sequence# should be enough to disambiguate) // decreasing type (though sequence# should be enough to disambiguate)
int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey));
BumpPerfCount(&perf_context.user_key_comparison_count); PERF_COUNTER_ADD(user_key_comparison_count, 1);
if (r == 0) { if (r == 0) {
const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8);
const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8);
@ -79,7 +79,7 @@ int InternalKeyComparator::Compare(const ParsedInternalKey& a,
// decreasing sequence number // decreasing sequence number
// decreasing type (though sequence# should be enough to disambiguate) // decreasing type (though sequence# should be enough to disambiguate)
int r = user_comparator_->Compare(a.user_key, b.user_key); int r = user_comparator_->Compare(a.user_key, b.user_key);
BumpPerfCount(&perf_context.user_key_comparison_count); PERF_COUNTER_ADD(user_key_comparison_count, 1);
if (r == 0) { if (r == 0) {
if (a.sequence > b.sequence) { if (a.sequence > b.sequence) {
r = -1; r = -1;

View file

@ -377,8 +377,7 @@ static bool SaveValue(void* arg, const char* entry) {
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s, bool MemTable::Get(const LookupKey& key, std::string* value, Status* s,
MergeContext& merge_context, const Options& options) { MergeContext& merge_context, const Options& options) {
StopWatchNano memtable_get_timer(options.env, false); PERF_TIMER_AUTO(get_from_memtable_time);
StartPerfTimer(&memtable_get_timer);
Slice user_key = key.user_key(); Slice user_key = key.user_key();
bool found_final_value = false; bool found_final_value = false;
@ -408,8 +407,8 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s,
if (!found_final_value && merge_in_progress) { if (!found_final_value && merge_in_progress) {
*s = Status::MergeInProgress(""); *s = Status::MergeInProgress("");
} }
BumpPerfTime(&perf_context.get_from_memtable_time, &memtable_get_timer); PERF_TIMER_STOP(get_from_memtable_time);
BumpPerfCount(&perf_context.get_from_memtable_count); PERF_COUNTER_ADD(get_from_memtable_count, 1);
return found_final_value; return found_final_value;
} }

View file

@ -64,7 +64,7 @@ struct PerfContext {
uint64_t write_memtable_time; uint64_t write_memtable_time;
}; };
#if defined(IOS_CROSS_COMPILE) #if defined(NPERF_CONTEXT) || defined(IOS_CROSS_COMPILE)
extern PerfContext perf_context; extern PerfContext perf_context;
#else #else
extern __thread PerfContext perf_context; extern __thread PerfContext perf_context;

View file

@ -107,7 +107,7 @@ Cache::Handle* GetEntryFromCache(Cache* block_cache, const Slice& key,
Statistics* statistics) { Statistics* statistics) {
auto cache_handle = block_cache->Lookup(key); auto cache_handle = block_cache->Lookup(key);
if (cache_handle != nullptr) { if (cache_handle != nullptr) {
BumpPerfCount(&perf_context.block_cache_hit_count); PERF_COUNTER_ADD(block_cache_hit_count, 1);
// overall cache hit // overall cache hit
RecordTick(statistics, BLOCK_CACHE_HIT); RecordTick(statistics, BLOCK_CACHE_HIT);
// block-type specific cache hit // block-type specific cache hit

View file

@ -125,12 +125,11 @@ Status ReadBlockContents(RandomAccessFile* file,
char* buf = new char[n + kBlockTrailerSize]; char* buf = new char[n + kBlockTrailerSize];
Slice contents; Slice contents;
StopWatchNano timer(env); PERF_TIMER_AUTO(block_read_time);
StartPerfTimer(&timer);
Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
BumpPerfCount(&perf_context.block_read_count); PERF_TIMER_MEASURE(block_read_time);
BumpPerfCount(&perf_context.block_read_byte, n + kBlockTrailerSize); PERF_COUNTER_ADD(block_read_count, 1);
BumpPerfTime(&perf_context.block_read_time, &timer); PERF_COUNTER_ADD(block_read_byte, n + kBlockTrailerSize);
if (!s.ok()) { if (!s.ok()) {
delete[] buf; delete[] buf;
@ -151,7 +150,7 @@ Status ReadBlockContents(RandomAccessFile* file,
s = Status::Corruption("block checksum mismatch"); s = Status::Corruption("block checksum mismatch");
return s; return s;
} }
BumpPerfTime(&perf_context.block_checksum_time, &timer); PERF_TIMER_MEASURE(block_checksum_time);
} }
// If the caller has requested that the block not be uncompressed // If the caller has requested that the block not be uncompressed
@ -175,7 +174,7 @@ Status ReadBlockContents(RandomAccessFile* file,
s = UncompressBlockContents(data, n, result); s = UncompressBlockContents(data, n, result);
delete[] buf; delete[] buf;
} }
BumpPerfTime(&perf_context.block_decompress_time, &timer); PERF_TIMER_STOP(block_decompress_time);
return s; return s;
} }

View file

@ -79,13 +79,13 @@ class MergingIterator : public Iterator {
// Invalidate the heap. // Invalidate the heap.
use_heap_ = false; use_heap_ = false;
IteratorWrapper* first_child = nullptr; IteratorWrapper* first_child = nullptr;
StopWatchNano child_seek_timer(env_, false); PERF_TIMER_DECLARE();
StopWatchNano min_heap_timer(env_, false);
for (auto& child : children_) { for (auto& child : children_) {
StartPerfTimer(&child_seek_timer); PERF_TIMER_START(seek_child_seek_time);
child.Seek(target); child.Seek(target);
BumpPerfTime(&perf_context.seek_child_seek_time, &child_seek_timer); PERF_TIMER_STOP(seek_child_seek_time);
BumpPerfCount(&perf_context.seek_child_seek_count); PERF_COUNTER_ADD(seek_child_seek_count, 1);
if (child.Valid()) { if (child.Valid()) {
// This child has valid key // This child has valid key
@ -97,26 +97,24 @@ class MergingIterator : public Iterator {
} else { } else {
// We have more than one children with valid keys. Initialize // We have more than one children with valid keys. Initialize
// the heap and put the first child into the heap. // the heap and put the first child into the heap.
StartPerfTimer(&min_heap_timer); PERF_TIMER_START(seek_min_heap_time);
ClearHeaps(); ClearHeaps();
BumpPerfTime(&perf_context.seek_min_heap_time, &child_seek_timer);
StartPerfTimer(&min_heap_timer);
minHeap_.push(first_child); minHeap_.push(first_child);
BumpPerfTime(&perf_context.seek_min_heap_time, &child_seek_timer); PERF_TIMER_STOP(seek_min_heap_time);
} }
} }
if (use_heap_) { if (use_heap_) {
StartPerfTimer(&min_heap_timer); PERF_TIMER_START(seek_min_heap_time);
minHeap_.push(&child); minHeap_.push(&child);
BumpPerfTime(&perf_context.seek_min_heap_time, &child_seek_timer); PERF_TIMER_STOP(seek_min_heap_time);
} }
} }
} }
if (use_heap_) { if (use_heap_) {
// If heap is valid, need to put the smallest key to curent_. // If heap is valid, need to put the smallest key to curent_.
StartPerfTimer(&min_heap_timer); PERF_TIMER_START(seek_min_heap_time);
FindSmallest(); FindSmallest();
BumpPerfTime(&perf_context.seek_min_heap_time, &child_seek_timer); PERF_TIMER_STOP(seek_min_heap_time);
} else { } else {
// The heap is not valid, then the current_ iterator is the first // The heap is not valid, then the current_ iterator is the first
// one, or null if there is no first child. // one, or null if there is no first child.

View file

@ -9,16 +9,21 @@
namespace rocksdb { namespace rocksdb {
// by default, enable counts only #if defined(NPERF_CONTEXT) || defined(IOS_CROSS_COMPILE)
#if defined(IOS_CROSS_COMPILE)
PerfLevel perf_level = kEnableCount; PerfLevel perf_level = kEnableCount;
// This is a dummy variable since some place references it
PerfContext perf_context;
#else #else
__thread PerfLevel perf_level = kEnableCount; __thread PerfLevel perf_level = kEnableCount;
__thread PerfContext perf_context;
#endif #endif
void SetPerfLevel(PerfLevel level) { perf_level = level; } void SetPerfLevel(PerfLevel level) {
perf_level = level;
}
void PerfContext::Reset() { void PerfContext::Reset() {
#if !defined(NPERF_CONTEXT) && !defined(IOS_CROSS_COMPILE)
user_key_comparison_count = 0; user_key_comparison_count = 0;
block_cache_hit_count = 0; block_cache_hit_count = 0;
block_read_count = 0; block_read_count = 0;
@ -42,11 +47,15 @@ void PerfContext::Reset() {
find_next_user_entry_time = 0; find_next_user_entry_time = 0;
write_pre_and_post_process_time = 0; write_pre_and_post_process_time = 0;
write_memtable_time = 0; write_memtable_time = 0;
#endif
} }
#define OUTPUT(counter) #counter << " = " << counter << ", " #define OUTPUT(counter) #counter << " = " << counter << ", "
std::string PerfContext::ToString() const { std::string PerfContext::ToString() const {
#if defined(NPERF_CONTEXT) || defined(IOS_CROSS_COMPILE)
return "";
#else
std::ostringstream ss; std::ostringstream ss;
ss << OUTPUT(user_key_comparison_count) ss << OUTPUT(user_key_comparison_count)
<< OUTPUT(block_cache_hit_count) << OUTPUT(block_cache_hit_count)
@ -71,11 +80,7 @@ std::string PerfContext::ToString() const {
<< OUTPUT(write_pre_and_post_process_time) << OUTPUT(write_pre_and_post_process_time)
<< OUTPUT(write_memtable_time); << OUTPUT(write_memtable_time);
return ss.str(); return ss.str();
}
#if defined(IOS_CROSS_COMPILE)
PerfContext perf_context;
#else
__thread PerfContext perf_context;
#endif #endif
} }
}

View file

@ -9,32 +9,80 @@
namespace rocksdb { namespace rocksdb {
// TODO(icanadi): when calling perf_context is macro-ed (TODO ljin), make it #if defined(NPERF_CONTEXT) || defined(IOS_CROSS_COMPILE)
// noop in case IOS_CROSS_COMPILE
#if defined(IOS_CROSS_COMPILE) #define PERF_TIMER_DECLARE()
extern enum PerfLevel perf_level; #define PERF_TIMER_START(metric)
#define PERF_TIMER_AUTO(metric)
#define PERF_TIMER_MEASURE(metric)
#define PERF_TIMER_STOP(metric)
#define PERF_COUNTER_ADD(metric, value)
#else #else
extern __thread PerfLevel perf_level; extern __thread PerfLevel perf_level;
class PerfStepTimer {
public:
PerfStepTimer()
: enabled_(perf_level >= PerfLevel::kEnableTime),
env_(enabled_ ? Env::Default() : nullptr),
start_(0) {
}
void Start() {
if (enabled_) {
start_ = env_->NowNanos();
}
}
void Measure(uint64_t* metric) {
if (start_) {
uint64_t now = env_->NowNanos();
*metric += now - start_;
start_ = now;
}
}
void Stop(uint64_t* metric) {
if (start_) {
*metric += env_->NowNanos() - start_;
start_ = 0;
}
}
private:
const bool enabled_;
Env* const env_;
uint64_t start_;
};
// Declare the local timer object to be used later on
#define PERF_TIMER_DECLARE() \
PerfStepTimer perf_step_timer;
// Set start time of the timer
#define PERF_TIMER_START(metric) \
perf_step_timer.Start();
// Declare and set start time of the timer
#define PERF_TIMER_AUTO(metric) \
PerfStepTimer perf_step_timer; \
perf_step_timer.Start();
// Update metric with time elapsed since last START. start time is reset
// to current timestamp.
#define PERF_TIMER_MEASURE(metric) \
perf_step_timer.Measure(&(perf_context.metric));
// Update metric with time elapsed since last START. But start time is not set.
#define PERF_TIMER_STOP(metric) \
perf_step_timer.Stop(&(perf_context.metric));
// Increase metric value
#define PERF_COUNTER_ADD(metric, value) \
perf_context.metric += value;
#endif #endif
inline void StartPerfTimer(StopWatchNano* timer) {
if (perf_level >= PerfLevel::kEnableTime) {
timer->Start();
}
}
inline void BumpPerfCount(uint64_t* count, uint64_t delta = 1) {
if (perf_level >= PerfLevel::kEnableCount) {
*count += delta;
}
}
inline void BumpPerfTime(uint64_t* time,
StopWatchNano* timer,
bool reset = true) {
if (perf_level >= PerfLevel::kEnableTime) {
*time += timer->ElapsedNanos(reset);
}
}
} }