1 /* 2 * Copyright 2013 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // A simple wall-clock profiler for instrumented code. 12 // Example: 13 // void MyLongFunction() { 14 // PROFILE_F(); // Time the execution of this function. 15 // // Do something 16 // { // Time just what is in this scope. 17 // PROFILE("My event"); 18 // // Do something else 19 // } 20 // } 21 // Another example: 22 // void StartAsyncProcess() { 23 // PROFILE_START("My async event"); 24 // DoSomethingAsyncAndThenCall(&Callback); 25 // } 26 // void Callback() { 27 // PROFILE_STOP("My async event"); 28 // // Handle callback. 29 // } 30 31 #ifndef WEBRTC_BASE_PROFILER_H_ 32 #define WEBRTC_BASE_PROFILER_H_ 33 34 #include <map> 35 #include <string> 36 37 #include "webrtc/base/basictypes.h" 38 #include "webrtc/base/common.h" 39 #include "webrtc/base/logging.h" 40 #include "webrtc/base/sharedexclusivelock.h" 41 42 // Profiling could be switched via a build flag, but for now, it's always on. 43 #ifndef ENABLE_PROFILING 44 #define ENABLE_PROFILING 45 #endif 46 47 #ifdef ENABLE_PROFILING 48 49 #define UV_HELPER2(x) _uv_ ## x 50 #define UV_HELPER(x) UV_HELPER2(x) 51 #define UNIQUE_VAR UV_HELPER(__LINE__) 52 53 // Profiles the current scope. 54 #define PROFILE(msg) rtc::ProfilerScope UNIQUE_VAR(msg) 55 // When placed at the start of a function, profiles the current function. 56 #define PROFILE_F() PROFILE(__FUNCTION__) 57 // Reports current timings to the log at severity |sev|. 58 #define PROFILE_DUMP_ALL(sev) \ 59 rtc::Profiler::Instance()->ReportAllToLog(__FILE__, __LINE__, sev) 60 // Reports current timings for all events whose names are prefixed by |prefix| 61 // to the log at severity |sev|. Using a unique event name as |prefix| will 62 // report only that event. 63 #define PROFILE_DUMP(sev, prefix) \ 64 rtc::Profiler::Instance()->ReportToLog(__FILE__, __LINE__, sev, prefix) 65 // Starts and stops a profile event. Useful when an event is not easily 66 // captured within a scope (eg, an async call with a callback when done). 67 #define PROFILE_START(msg) rtc::Profiler::Instance()->StartEvent(msg) 68 #define PROFILE_STOP(msg) rtc::Profiler::Instance()->StopEvent(msg) 69 // TODO(ryanpetrie): Consider adding PROFILE_DUMP_EVERY(sev, iterations) 70 71 #undef UV_HELPER2 72 #undef UV_HELPER 73 #undef UNIQUE_VAR 74 75 #else // ENABLE_PROFILING 76 77 #define PROFILE(msg) (void)0 78 #define PROFILE_F() (void)0 79 #define PROFILE_DUMP_ALL(sev) (void)0 80 #define PROFILE_DUMP(sev, prefix) (void)0 81 #define PROFILE_START(msg) (void)0 82 #define PROFILE_STOP(msg) (void)0 83 84 #endif // ENABLE_PROFILING 85 86 namespace rtc { 87 88 // Tracks information for one profiler event. 89 class ProfilerEvent { 90 public: 91 ProfilerEvent(); 92 void Start(); 93 void Stop(); 94 void Stop(uint64 stop_time); 95 double standard_deviation() const; total_time()96 double total_time() const { return total_time_; } mean()97 double mean() const { return mean_; } minimum()98 double minimum() const { return minimum_; } maximum()99 double maximum() const { return maximum_; } event_count()100 int event_count() const { return event_count_; } is_started()101 bool is_started() const { return start_count_ > 0; } 102 103 private: 104 uint64 current_start_time_; 105 double total_time_; 106 double mean_; 107 double sum_of_squared_differences_; 108 double minimum_; 109 double maximum_; 110 int start_count_; 111 int event_count_; 112 }; 113 114 // Singleton that owns ProfilerEvents and reports results. Prefer to use 115 // macros, defined above, rather than directly calling Profiler methods. 116 class Profiler { 117 public: 118 void StartEvent(const std::string& event_name); 119 void StopEvent(const std::string& event_name); 120 void ReportToLog(const char* file, int line, LoggingSeverity severity_to_use, 121 const std::string& event_prefix); 122 void ReportAllToLog(const char* file, int line, 123 LoggingSeverity severity_to_use); 124 const ProfilerEvent* GetEvent(const std::string& event_name) const; 125 // Clears all _stopped_ events. Returns true if _all_ events were cleared. 126 bool Clear(); 127 128 static Profiler* Instance(); 129 private: Profiler()130 Profiler() {} 131 132 typedef std::map<std::string, ProfilerEvent> EventMap; 133 EventMap events_; 134 mutable SharedExclusiveLock lock_; 135 136 DISALLOW_COPY_AND_ASSIGN(Profiler); 137 }; 138 139 // Starts an event on construction and stops it on destruction. 140 // Used by PROFILE macro. 141 class ProfilerScope { 142 public: ProfilerScope(const std::string & event_name)143 explicit ProfilerScope(const std::string& event_name) 144 : event_name_(event_name) { 145 Profiler::Instance()->StartEvent(event_name_); 146 } ~ProfilerScope()147 ~ProfilerScope() { 148 Profiler::Instance()->StopEvent(event_name_); 149 } 150 private: 151 std::string event_name_; 152 153 DISALLOW_COPY_AND_ASSIGN(ProfilerScope); 154 }; 155 156 std::ostream& operator<<(std::ostream& stream, 157 const ProfilerEvent& profiler_event); 158 159 } // namespace rtc 160 161 #endif // WEBRTC_BASE_PROFILER_H_ 162