1 /* 2 * libjingle 3 * Copyright 2013, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 // A simple wall-clock profiler for instrumented code. 29 // Example: 30 // void MyLongFunction() { 31 // PROFILE_F(); // Time the execution of this function. 32 // // Do something 33 // { // Time just what is in this scope. 34 // PROFILE("My event"); 35 // // Do something else 36 // } 37 // } 38 // Another example: 39 // void StartAsyncProcess() { 40 // PROFILE_START("My async event"); 41 // DoSomethingAsyncAndThenCall(&Callback); 42 // } 43 // void Callback() { 44 // PROFILE_STOP("My async event"); 45 // // Handle callback. 46 // } 47 48 #ifndef TALK_BASE_PROFILER_H_ 49 #define TALK_BASE_PROFILER_H_ 50 51 #include <map> 52 #include <string> 53 54 #include "talk/base/basictypes.h" 55 #include "talk/base/common.h" 56 #include "talk/base/logging.h" 57 #include "talk/base/sharedexclusivelock.h" 58 59 // Profiling could be switched via a build flag, but for now, it's always on. 60 #ifndef ENABLE_PROFILING 61 #define ENABLE_PROFILING 62 #endif 63 64 #ifdef ENABLE_PROFILING 65 66 #define UV_HELPER2(x) _uv_ ## x 67 #define UV_HELPER(x) UV_HELPER2(x) 68 #define UNIQUE_VAR UV_HELPER(__LINE__) 69 70 // Profiles the current scope. 71 #define PROFILE(msg) talk_base::ProfilerScope UNIQUE_VAR(msg) 72 // When placed at the start of a function, profiles the current function. 73 #define PROFILE_F() PROFILE(__FUNCTION__) 74 // Reports current timings to the log at severity |sev|. 75 #define PROFILE_DUMP_ALL(sev) \ 76 talk_base::Profiler::Instance()->ReportAllToLog(__FILE__, __LINE__, sev) 77 // Reports current timings for all events whose names are prefixed by |prefix| 78 // to the log at severity |sev|. Using a unique event name as |prefix| will 79 // report only that event. 80 #define PROFILE_DUMP(sev, prefix) \ 81 talk_base::Profiler::Instance()->ReportToLog(__FILE__, __LINE__, sev, prefix) 82 // Starts and stops a profile event. Useful when an event is not easily 83 // captured within a scope (eg, an async call with a callback when done). 84 #define PROFILE_START(msg) talk_base::Profiler::Instance()->StartEvent(msg) 85 #define PROFILE_STOP(msg) talk_base::Profiler::Instance()->StopEvent(msg) 86 // TODO(ryanpetrie): Consider adding PROFILE_DUMP_EVERY(sev, iterations) 87 88 #undef UV_HELPER2 89 #undef UV_HELPER 90 #undef UNIQUE_VAR 91 92 #else // ENABLE_PROFILING 93 94 #define PROFILE(msg) (void)0 95 #define PROFILE_F() (void)0 96 #define PROFILE_DUMP_ALL(sev) (void)0 97 #define PROFILE_DUMP(sev, prefix) (void)0 98 #define PROFILE_START(msg) (void)0 99 #define PROFILE_STOP(msg) (void)0 100 101 #endif // ENABLE_PROFILING 102 103 namespace talk_base { 104 105 // Tracks information for one profiler event. 106 class ProfilerEvent { 107 public: 108 ProfilerEvent(); 109 void Start(); 110 void Stop(); 111 void Stop(uint64 stop_time); 112 double standard_deviation() const; total_time()113 double total_time() const { return total_time_; } mean()114 double mean() const { return mean_; } minimum()115 double minimum() const { return minimum_; } maximum()116 double maximum() const { return maximum_; } event_count()117 int event_count() const { return event_count_; } is_started()118 bool is_started() const { return start_count_ > 0; } 119 120 private: 121 uint64 current_start_time_; 122 double total_time_; 123 double mean_; 124 double sum_of_squared_differences_; 125 double minimum_; 126 double maximum_; 127 int start_count_; 128 int event_count_; 129 }; 130 131 // Singleton that owns ProfilerEvents and reports results. Prefer to use 132 // macros, defined above, rather than directly calling Profiler methods. 133 class Profiler { 134 public: 135 void StartEvent(const std::string& event_name); 136 void StopEvent(const std::string& event_name); 137 void ReportToLog(const char* file, int line, LoggingSeverity severity_to_use, 138 const std::string& event_prefix); 139 void ReportAllToLog(const char* file, int line, 140 LoggingSeverity severity_to_use); 141 const ProfilerEvent* GetEvent(const std::string& event_name) const; 142 // Clears all _stopped_ events. Returns true if _all_ events were cleared. 143 bool Clear(); 144 145 static Profiler* Instance(); 146 private: Profiler()147 Profiler() {} 148 149 typedef std::map<std::string, ProfilerEvent> EventMap; 150 EventMap events_; 151 mutable SharedExclusiveLock lock_; 152 153 DISALLOW_COPY_AND_ASSIGN(Profiler); 154 }; 155 156 // Starts an event on construction and stops it on destruction. 157 // Used by PROFILE macro. 158 class ProfilerScope { 159 public: ProfilerScope(const std::string & event_name)160 explicit ProfilerScope(const std::string& event_name) 161 : event_name_(event_name) { 162 Profiler::Instance()->StartEvent(event_name_); 163 } ~ProfilerScope()164 ~ProfilerScope() { 165 Profiler::Instance()->StopEvent(event_name_); 166 } 167 private: 168 std::string event_name_; 169 170 DISALLOW_COPY_AND_ASSIGN(ProfilerScope); 171 }; 172 173 std::ostream& operator<<(std::ostream& stream, 174 const ProfilerEvent& profiler_event); 175 176 } // namespace talk_base 177 178 #endif // TALK_BASE_PROFILER_H_ 179