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