Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "metrics.h" 00016 00017 #include <errno.h> 00018 #include <stdio.h> 00019 #include <string.h> 00020 00021 #ifndef _WIN32 00022 #include <sys/time.h> 00023 #else 00024 #include <windows.h> 00025 #endif 00026 00027 #include "util.h" 00028 00029 Metrics* g_metrics = NULL; 00030 00031 namespace { 00032 00033 #ifndef _WIN32 00034 /// Compute a platform-specific high-res timer value that fits into an int64. 00035 int64_t HighResTimer() { 00036 timeval tv; 00037 if (gettimeofday(&tv, NULL) < 0) 00038 Fatal("gettimeofday: %s", strerror(errno)); 00039 return (int64_t)tv.tv_sec * 1000*1000 + tv.tv_usec; 00040 } 00041 00042 /// Convert a delta of HighResTimer() values to microseconds. 00043 int64_t TimerToMicros(int64_t dt) { 00044 // No conversion necessary. 00045 return dt; 00046 } 00047 #else 00048 int64_t LargeIntegerToInt64(const LARGE_INTEGER& i) { 00049 return ((int64_t)i.HighPart) << 32 | i.LowPart; 00050 } 00051 00052 int64_t HighResTimer() { 00053 LARGE_INTEGER counter; 00054 if (!QueryPerformanceCounter(&counter)) 00055 Fatal("QueryPerformanceCounter: %s", GetLastErrorString().c_str()); 00056 return LargeIntegerToInt64(counter); 00057 } 00058 00059 int64_t TimerToMicros(int64_t dt) { 00060 static int64_t ticks_per_sec = 0; 00061 if (!ticks_per_sec) { 00062 LARGE_INTEGER freq; 00063 if (!QueryPerformanceFrequency(&freq)) 00064 Fatal("QueryPerformanceFrequency: %s", GetLastErrorString().c_str()); 00065 ticks_per_sec = LargeIntegerToInt64(freq); 00066 } 00067 00068 // dt is in ticks. We want microseconds. 00069 return (dt * 1000000) / ticks_per_sec; 00070 } 00071 #endif 00072 00073 } // anonymous namespace 00074 00075 00076 ScopedMetric::ScopedMetric(Metric* metric) { 00077 metric_ = metric; 00078 if (!metric_) 00079 return; 00080 start_ = HighResTimer(); 00081 } 00082 ScopedMetric::~ScopedMetric() { 00083 if (!metric_) 00084 return; 00085 metric_->count++; 00086 int64_t dt = TimerToMicros(HighResTimer() - start_); 00087 metric_->sum += dt; 00088 } 00089 00090 Metric* Metrics::NewMetric(const string& name) { 00091 Metric* metric = new Metric; 00092 metric->name = name; 00093 metric->count = 0; 00094 metric->sum = 0; 00095 metrics_.push_back(metric); 00096 return metric; 00097 } 00098 00099 void Metrics::Report() { 00100 int width = 0; 00101 for (vector<Metric*>::iterator i = metrics_.begin(); 00102 i != metrics_.end(); ++i) { 00103 width = max((int)(*i)->name.size(), width); 00104 } 00105 00106 printf("%-*s\t%-6s\t%-9s\t%s\n", width, 00107 "metric", "count", "avg (us)", "total (ms)"); 00108 for (vector<Metric*>::iterator i = metrics_.begin(); 00109 i != metrics_.end(); ++i) { 00110 Metric* metric = *i; 00111 double total = metric->sum / (double)1000; 00112 double avg = metric->sum / (double)metric->count; 00113 printf("%-*s\t%-6d\t%-8.1f\t%.1f\n", width, metric->name.c_str(), 00114 metric->count, avg, total); 00115 } 00116 } 00117 00118 uint64_t Stopwatch::Now() const { 00119 return TimerToMicros(HighResTimer()); 00120 } 00121 00122 int64_t GetTimeMillis() { 00123 return TimerToMicros(HighResTimer()) / 1000; 00124 } 00125