Home | History | Annotate | Download | only in base
      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;
     96   double total_time() const { return total_time_; }
     97   double mean() const { return mean_; }
     98   double minimum() const { return minimum_; }
     99   double maximum() const { return maximum_; }
    100   int event_count() const { return event_count_; }
    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:
    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:
    143   explicit ProfilerScope(const std::string& event_name)
    144       : event_name_(event_name) {
    145     Profiler::Instance()->StartEvent(event_name_);
    146   }
    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