aboutsummaryrefslogtreecommitdiffstats
path: root/src/stats.cc
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2020-06-29 22:33:05 -0700
committerDan Willemsen <dwillemsen@google.com>2020-06-29 22:33:05 -0700
commit5125da301ca0a1680c26b5d9f574dc174fdfa98c (patch)
treedb93815340f8e87080791cf7bc93e135234e9387 /src/stats.cc
parente184ff147273cfd25d37692dba4be72eca571e9f (diff)
parent06a798c4db92ec3a3a6b3a4b52026f002002affa (diff)
downloadplatform_build_kati-5125da301ca0a1680c26b5d9f574dc174fdfa98c.tar.gz
platform_build_kati-5125da301ca0a1680c26b5d9f574dc174fdfa98c.tar.bz2
platform_build_kati-5125da301ca0a1680c26b5d9f574dc174fdfa98c.zip
Merge remote-tracking branch 'aosp/upstream'HEADmaster
* aosp/upstream: Support git submodules in version.cc generation. Link ckati against jemalloc if host machine runs Linux. Support building in a git worktree Fix flaky test Switch to a golang-based test runner Refactor source tree into directories Test: treehugger Change-Id: I6cca6108531c4c32e3848bf6b532a99aef0f06c2
Diffstat (limited to 'src/stats.cc')
-rw-r--r--src/stats.cc145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/stats.cc b/src/stats.cc
new file mode 100644
index 0000000..be03774
--- /dev/null
+++ b/src/stats.cc
@@ -0,0 +1,145 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build ignore
+
+#include "stats.h"
+
+#include <algorithm>
+#include <mutex>
+#include <vector>
+
+#include "find.h"
+#include "flags.h"
+#include "log.h"
+#include "stringprintf.h"
+#include "timeutil.h"
+
+namespace {
+
+mutex g_mu;
+vector<Stats*>* g_stats;
+
+} // namespace
+
+Stats::Stats(const char* name) : name_(name), elapsed_(0), cnt_(0) {
+ unique_lock<mutex> lock(g_mu);
+ if (g_stats == NULL)
+ g_stats = new vector<Stats*>;
+ g_stats->push_back(this);
+}
+
+void Stats::DumpTop() const {
+ unique_lock<mutex> lock(mu_);
+ if (detailed_.size() > 0) {
+ vector<pair<string, StatsDetails>> details(detailed_.begin(),
+ detailed_.end());
+ sort(details.begin(), details.end(),
+ [](const pair<string, StatsDetails> a,
+ const pair<string, StatsDetails> b) -> bool {
+ return a.second.elapsed_ > b.second.elapsed_;
+ });
+
+ // Only print the top 10
+ details.resize(min(details.size(), static_cast<size_t>(10)));
+
+ if (!interesting_.empty()) {
+ // No need to print anything out twice
+ auto interesting = interesting_;
+ for (auto& [n, detail] : details) {
+ interesting.erase(n);
+ }
+
+ for (auto& name : interesting) {
+ auto detail = detailed_.find(name);
+ if (detail == detailed_.end()) {
+ details.emplace_back(name, StatsDetails());
+ continue;
+ }
+ details.emplace_back(*detail);
+ }
+ }
+
+ int max_cnt_len = 1;
+ for (auto& [name, detail] : details) {
+ max_cnt_len =
+ max(max_cnt_len, static_cast<int>(to_string(detail.cnt_).length()));
+ }
+
+ for (auto& [name, detail] : details) {
+ LOG_STAT(" %6.3f / %*d %s", detail.elapsed_, max_cnt_len, detail.cnt_,
+ name.c_str());
+ }
+ }
+}
+
+string Stats::String() const {
+ unique_lock<mutex> lock(mu_);
+ if (!detailed_.empty())
+ return StringPrintf("%s: %f / %d (%d unique)", name_, elapsed_, cnt_,
+ detailed_.size());
+ return StringPrintf("%s: %f / %d", name_, elapsed_, cnt_);
+}
+
+double Stats::Start() {
+ double start = GetTime();
+ unique_lock<mutex> lock(mu_);
+ cnt_++;
+ return start;
+}
+
+double Stats::End(double start, const char* msg) {
+ double e = GetTime() - start;
+ unique_lock<mutex> lock(mu_);
+ elapsed_ += e;
+ if (msg != 0) {
+ StatsDetails& details = detailed_[string(msg)];
+ details.elapsed_ += e;
+ details.cnt_++;
+ }
+ return e;
+}
+
+void Stats::MarkInteresting(const string& msg) {
+ unique_lock<mutex> lock(mu_);
+ interesting_.emplace(msg);
+}
+
+ScopedStatsRecorder::ScopedStatsRecorder(Stats* st, const char* msg)
+ : st_(st), msg_(msg), start_time_(0) {
+ if (!g_flags.enable_stat_logs)
+ return;
+ start_time_ = st_->Start();
+}
+
+ScopedStatsRecorder::~ScopedStatsRecorder() {
+ if (!g_flags.enable_stat_logs)
+ return;
+ double e = st_->End(start_time_, msg_);
+ if (msg_ && e > 3.0) {
+ LOG_STAT("slow %s (%f): %s", st_->name_, e, msg_);
+ }
+}
+
+void ReportAllStats() {
+ if (!g_stats)
+ return;
+ for (Stats* st : *g_stats) {
+ LOG_STAT("%s", st->String().c_str());
+ st->DumpTop();
+ }
+ delete g_stats;
+
+ LOG_STAT("%u find nodes", FindEmulator::GetNodeCount());
+}