blob: f74a540ae47a219b6b29d65cf4ddd2372ec623d2 [file] [log] [blame]
henrike@webrtc.org0e118e72013-07-10 00:45:36 +00001/*
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() {
wu@webrtc.orgd1f631d2013-10-30 05:18:12 +000040// PROFILE_START("My async event");
henrike@webrtc.org0e118e72013-07-10 00:45:36 +000041// 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"
wu@webrtc.orgd1f631d2013-10-30 05:18:12 +000057#include "talk/base/sharedexclusivelock.h"
henrike@webrtc.org0e118e72013-07-10 00:45:36 +000058
59// Profiling could be switched via a build flag, but for now, it's always on.
andrew@webrtc.orge7dd32d2014-03-27 22:44:13 +000060#ifndef ENABLE_PROFILING
henrike@webrtc.org0e118e72013-07-10 00:45:36 +000061#define ENABLE_PROFILING
andrew@webrtc.orge7dd32d2014-03-27 22:44:13 +000062#endif
henrike@webrtc.org0e118e72013-07-10 00:45:36 +000063
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
103namespace talk_base {
104
105// Tracks information for one profiler event.
106class ProfilerEvent {
107 public:
108 ProfilerEvent();
109 void Start();
110 void Stop();
wu@webrtc.orgd1f631d2013-10-30 05:18:12 +0000111 void Stop(uint64 stop_time);
henrike@webrtc.org0e118e72013-07-10 00:45:36 +0000112 double standard_deviation() const;
113 double total_time() const { return total_time_; }
114 double mean() const { return mean_; }
115 double minimum() const { return minimum_; }
116 double maximum() const { return maximum_; }
117 int event_count() const { return event_count_; }
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.
133class 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:
147 Profiler() {}
148
wu@webrtc.orgd1f631d2013-10-30 05:18:12 +0000149 typedef std::map<std::string, ProfilerEvent> EventMap;
150 EventMap events_;
151 mutable SharedExclusiveLock lock_;
henrike@webrtc.org0e118e72013-07-10 00:45:36 +0000152
153 DISALLOW_COPY_AND_ASSIGN(Profiler);
154};
155
156// Starts an event on construction and stops it on destruction.
157// Used by PROFILE macro.
158class ProfilerScope {
159 public:
160 explicit ProfilerScope(const std::string& event_name)
161 : event_name_(event_name) {
162 Profiler::Instance()->StartEvent(event_name_);
163 }
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
wu@webrtc.org861d0732013-10-07 23:32:02 +0000173std::ostream& operator<<(std::ostream& stream,
174 const ProfilerEvent& profiler_event);
175
henrike@webrtc.org0e118e72013-07-10 00:45:36 +0000176} // namespace talk_base
177
178#endif // TALK_BASE_PROFILER_H_