1 // Copyright 2015 Google Inc. All rights reserved 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build ignore 16 17 #include "stats.h" 18 19 #include <mutex> 20 #include <vector> 21 22 #include "flags.h" 23 #include "log.h" 24 #include "stringprintf.h" 25 #include "thread_local.h" 26 #include "timeutil.h" 27 28 namespace { 29 30 mutex g_mu; 31 vector<Stats*>* g_stats; 32 DEFINE_THREAD_LOCAL(double, g_start_time); 33 34 } // namespace 35 36 Stats::Stats(const char* name) 37 : name_(name), elapsed_(0), cnt_(0) { 38 unique_lock<mutex> lock(g_mu); 39 if (g_stats == NULL) 40 g_stats = new vector<Stats*>; 41 g_stats->push_back(this); 42 } 43 44 string Stats::String() const { 45 unique_lock<mutex> lock(mu_); 46 return StringPrintf("%s: %f / %d", name_, elapsed_, cnt_); 47 } 48 49 void Stats::Start() { 50 CHECK(!TLS_REF(g_start_time)); 51 TLS_REF(g_start_time) = GetTime(); 52 unique_lock<mutex> lock(mu_); 53 cnt_++; 54 } 55 56 double Stats::End() { 57 CHECK(TLS_REF(g_start_time)); 58 double e = GetTime() - TLS_REF(g_start_time); 59 TLS_REF(g_start_time) = 0; 60 unique_lock<mutex> lock(mu_); 61 elapsed_ += e; 62 return e; 63 } 64 65 ScopedStatsRecorder::ScopedStatsRecorder(Stats* st, const char* msg) 66 : st_(st), msg_(msg) { 67 if (!g_flags.enable_stat_logs) 68 return; 69 st_->Start(); 70 } 71 72 ScopedStatsRecorder::~ScopedStatsRecorder() { 73 if (!g_flags.enable_stat_logs) 74 return; 75 double e = st_->End(); 76 if (msg_ && e > 3.0) { 77 LOG_STAT("slow %s (%f): %s", st_->name_, e, msg_); 78 } 79 } 80 81 void ReportAllStats() { 82 if (!g_stats) 83 return; 84 for (Stats* st : *g_stats) { 85 LOG_STAT("%s", st->String().c_str()); 86 } 87 delete g_stats; 88 } 89