• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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