3 * Copyright 2013, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
28 // A simple wall-clock profiler for instrumented code.
30 // void MyLongFunction() {
31 // PROFILE_F(); // Time the execution of this function.
33 // { // Time just what is in this scope.
34 // PROFILE("My event");
35 // // Do something else
39 // void StartAsyncProcess() {
40 // PROFILE_START("My async event");
41 // DoSomethingAsyncAndThenCall(&Callback);
44 // PROFILE_STOP("My async event");
45 // // Handle callback.
48 #ifndef TALK_BASE_PROFILER_H_
49 #define TALK_BASE_PROFILER_H_
54 #include "talk/base/basictypes.h"
55 #include "talk/base/common.h"
56 #include "talk/base/logging.h"
57 #include "talk/base/sharedexclusivelock.h"
59 // Profiling could be switched via a build flag, but for now, it's always on.
60 #define ENABLE_PROFILING
62 #ifdef ENABLE_PROFILING
64 #define UV_HELPER2(x) _uv_ ## x
65 #define UV_HELPER(x) UV_HELPER2(x)
66 #define UNIQUE_VAR UV_HELPER(__LINE__)
68 // Profiles the current scope.
69 #define PROFILE(msg) talk_base::ProfilerScope UNIQUE_VAR(msg)
70 // When placed at the start of a function, profiles the current function.
71 #define PROFILE_F() PROFILE(__FUNCTION__)
72 // Reports current timings to the log at severity |sev|.
73 #define PROFILE_DUMP_ALL(sev) \
74 talk_base::Profiler::Instance()->ReportAllToLog(__FILE__, __LINE__, sev)
75 // Reports current timings for all events whose names are prefixed by |prefix|
76 // to the log at severity |sev|. Using a unique event name as |prefix| will
77 // report only that event.
78 #define PROFILE_DUMP(sev, prefix) \
79 talk_base::Profiler::Instance()->ReportToLog(__FILE__, __LINE__, sev, prefix)
80 // Starts and stops a profile event. Useful when an event is not easily
81 // captured within a scope (eg, an async call with a callback when done).
82 #define PROFILE_START(msg) talk_base::Profiler::Instance()->StartEvent(msg)
83 #define PROFILE_STOP(msg) talk_base::Profiler::Instance()->StopEvent(msg)
84 // TODO(ryanpetrie): Consider adding PROFILE_DUMP_EVERY(sev, iterations)
90 #else // ENABLE_PROFILING
92 #define PROFILE(msg) (void)0
93 #define PROFILE_F() (void)0
94 #define PROFILE_DUMP_ALL(sev) (void)0
95 #define PROFILE_DUMP(sev, prefix) (void)0
96 #define PROFILE_START(msg) (void)0
97 #define PROFILE_STOP(msg) (void)0
99 #endif // ENABLE_PROFILING
101 namespace talk_base {
103 // Tracks information for one profiler event.
104 class ProfilerEvent {
109 void Stop(uint64 stop_time);
110 double standard_deviation() const;
111 double total_time() const { return total_time_; }
112 double mean() const { return mean_; }
113 double minimum() const { return minimum_; }
114 double maximum() const { return maximum_; }
115 int event_count() const { return event_count_; }
116 bool is_started() const { return start_count_ > 0; }
119 uint64 current_start_time_;
122 double sum_of_squared_differences_;
129 // Singleton that owns ProfilerEvents and reports results. Prefer to use
130 // macros, defined above, rather than directly calling Profiler methods.
133 void StartEvent(const std::string& event_name);
134 void StopEvent(const std::string& event_name);
135 void ReportToLog(const char* file, int line, LoggingSeverity severity_to_use,
136 const std::string& event_prefix);
137 void ReportAllToLog(const char* file, int line,
138 LoggingSeverity severity_to_use);
139 const ProfilerEvent* GetEvent(const std::string& event_name) const;
140 // Clears all _stopped_ events. Returns true if _all_ events were cleared.
143 static Profiler* Instance();
147 typedef std::map<std::string, ProfilerEvent> EventMap;
149 mutable SharedExclusiveLock lock_;
151 DISALLOW_COPY_AND_ASSIGN(Profiler);
154 // Starts an event on construction and stops it on destruction.
155 // Used by PROFILE macro.
156 class ProfilerScope {
158 explicit ProfilerScope(const std::string& event_name)
159 : event_name_(event_name) {
160 Profiler::Instance()->StartEvent(event_name_);
163 Profiler::Instance()->StopEvent(event_name_);
166 std::string event_name_;
168 DISALLOW_COPY_AND_ASSIGN(ProfilerScope);
171 std::ostream& operator<<(std::ostream& stream,
172 const ProfilerEvent& profiler_event);
174 } // namespace talk_base
176 #endif // TALK_BASE_PROFILER_H_