diff options
author | Evan Martin <martine@danga.com> | 2012-01-05 21:35:47 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2012-01-05 22:03:55 (GMT) |
commit | d5165bafdabbfba23d33a5e0ceb9e0e680384183 (patch) | |
tree | 7f61a5d96d62c1f75d60b761b7d1059a0783c2bd /src/metrics.cc | |
parent | 9e31e01595656cc2dacd2f97fb6e765799518254 (diff) | |
download | Ninja-d5165bafdabbfba23d33a5e0ceb9e0e680384183.zip Ninja-d5165bafdabbfba23d33a5e0ceb9e0e680384183.tar.gz Ninja-d5165bafdabbfba23d33a5e0ceb9e0e680384183.tar.bz2 |
add a '-d stats' flag for detailed timings
1) Add a system for recording detailed timing info of functions.
2) Add a -d flag for requesting debug info at runtime, with the
above as the first user.
Diffstat (limited to 'src/metrics.cc')
-rw-r--r-- | src/metrics.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/metrics.cc b/src/metrics.cc new file mode 100644 index 0000000..07caade --- /dev/null +++ b/src/metrics.cc @@ -0,0 +1,108 @@ +// Copyright 2011 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. + +#include "metrics.h" + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifndef WIN32 +#include <sys/time.h> +#else +#include <windows.h> +#endif + +#include "util.h" + +Metrics* g_metrics = NULL; + +namespace { + +#ifndef WIN32 +/// Compute a platform-specific high-res timer value that fits into an int64. +int64_t HighResTimer() { + timeval tv; + if (gettimeofday(&tv, NULL) < 0) + Fatal("gettimeofday: %s", strerror(errno)); + return (int64_t)tv.tv_sec * 1000*1000 + tv.tv_usec; +} + +/// Convert a delta of HighResTimer() values to microseconds. +int64_t TimerToMicros(int64_t dt) { + // No conversion necessary. + return dt; +} +#else +int64_t LargeIntegerToInt64(const LARGE_INTEGER& i) { + return ((int64_t)i.HighPart) << 32 | i.LowPart; +} + +int64_t HighResTimer() { + LARGE_INTEGER counter; + if (!QueryPerformanceCounter(&counter)) + Fatal("QueryPerformanceCounter: %s", GetLastErrorString().c_str()); + return LargeIntegerToInt64(counter); +} + +int64_t TimerToMicros(int64_t dt) { + static int64_t ticks_per_sec = 0; + if (!ticks_per_sec) { + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) + Fatal("QueryPerformanceFrequency: %s", GetLastErrorString().c_str()); + ticks_per_sec = LargeIntegerToInt64(freq); + } + + // dt is in ticks. We want microseconds. + return (dt * 1000000) / ticks_per_sec; +} +#endif + +} // anonymous namespace + +ScopedMetric::ScopedMetric(Metric* metric) { + metric_ = metric; + if (!metric_) + return; + start_ = HighResTimer(); +} +ScopedMetric::~ScopedMetric() { + if (!metric_) + return; + metric_->count++; + int64_t dt = TimerToMicros(HighResTimer() - start_); + metric_->sum += dt; +} + +Metric* Metrics::NewMetric(const string& name) { + Metric* metric = new Metric; + metric->name = name; + metric->count = 0; + metric->sum = 0; + metrics_.push_back(metric); + return metric; +} + +void Metrics::Report() { + printf("%-10s\t%-6s\t%9s\t%s\n", + "metric", "count", "total (ms)" , "avg (us)"); + for (vector<Metric*>::iterator i = metrics_.begin(); i != metrics_.end(); ++i) { + Metric* metric = *i; + double total = metric->sum / (double)1000; + double avg = metric->sum / (double)metric->count; + printf("%-10s\t%-6d\t%-8.1f\t%.1f\n", metric->name.c_str(), + metric->count, total, avg); + } +} |