/*
* Copyright 2013 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// A simple wall-clock profiler for instrumented code.
// Example:
// void MyLongFunction() {
// PROFILE_F(); // Time the execution of this function.
// // Do something
// { // Time just what is in this scope.
// PROFILE("My event");
// // Do something else
// }
// }
// Another example:
// void StartAsyncProcess() {
// PROFILE_START("My async event");
// DoSomethingAsyncAndThenCall(&Callback);
// }
// void Callback() {
// PROFILE_STOP("My async event");
// // Handle callback.
// }
#ifndef WEBRTC_BASE_PROFILER_H_
#define WEBRTC_BASE_PROFILER_H_
#include <map>
#include <string>
#include "webrtc/base/basictypes.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/sharedexclusivelock.h"
// Profiling could be switched via a build flag, but for now, it's always on.
#ifndef ENABLE_PROFILING
#define ENABLE_PROFILING
#endif
#ifdef ENABLE_PROFILING
#define UV_HELPER2(x) _uv_ ## x
#define UV_HELPER(x) UV_HELPER2(x)
#define UNIQUE_VAR UV_HELPER(__LINE__)
// Profiles the current scope.
#define PROFILE(msg) rtc::ProfilerScope UNIQUE_VAR(msg)
// When placed at the start of a function, profiles the current function.
#define PROFILE_F() PROFILE(__FUNCTION__)
// Reports current timings to the log at severity |sev|.
#define PROFILE_DUMP_ALL(sev) \
rtc::Profiler::Instance()->ReportAllToLog(__FILE__, __LINE__, sev)
// Reports current timings for all events whose names are prefixed by |prefix|
// to the log at severity |sev|. Using a unique event name as |prefix| will
// report only that event.
#define PROFILE_DUMP(sev, prefix) \
rtc::Profiler::Instance()->ReportToLog(__FILE__, __LINE__, sev, prefix)
// Starts and stops a profile event. Useful when an event is not easily
// captured within a scope (eg, an async call with a callback when done).
#define PROFILE_START(msg) rtc::Profiler::Instance()->StartEvent(msg)
#define PROFILE_STOP(msg) rtc::Profiler::Instance()->StopEvent(msg)
// TODO(ryanpetrie): Consider adding PROFILE_DUMP_EVERY(sev, iterations)
#undef UV_HELPER2
#undef UV_HELPER
#undef UNIQUE_VAR
#else // ENABLE_PROFILING
#define PROFILE(msg) (void)0
#define PROFILE_F() (void)0
#define PROFILE_DUMP_ALL(sev) (void)0
#define PROFILE_DUMP(sev, prefix) (void)0
#define PROFILE_START(msg) (void)0
#define PROFILE_STOP(msg) (void)0
#endif // ENABLE_PROFILING
namespace rtc {
// Tracks information for one profiler event.
class ProfilerEvent {
public:
ProfilerEvent();
void Start();
void Stop();
void Stop(uint64 stop_time);
double standard_deviation() const;
double total_time() const { return total_time_; }
double mean() const { return mean_; }
double minimum() const { return minimum_; }
double maximum() const { return maximum_; }
int event_count() const { return event_count_; }
bool is_started() const { return start_count_ > 0; }
private:
uint64 current_start_time_;
double total_time_;
double mean_;
double sum_of_squared_differences_;
double minimum_;
double maximum_;
int start_count_;
int event_count_;
};
// Singleton that owns ProfilerEvents and reports results. Prefer to use
// macros, defined above, rather than directly calling Profiler methods.
class Profiler {
public:
void StartEvent(const std::string& event_name);
void StopEvent(const std::string& event_name);
void ReportToLog(const char* file, int line, LoggingSeverity severity_to_use,
const std::string& event_prefix);
void ReportAllToLog(const char* file, int line,
LoggingSeverity severity_to_use);
const ProfilerEvent* GetEvent(const std::string& event_name) const;
// Clears all _stopped_ events. Returns true if _all_ events were cleared.
bool Clear();
static Profiler* Instance();
private:
Profiler() {}
typedef std::map<std::string, ProfilerEvent> EventMap;
EventMap events_;
mutable SharedExclusiveLock lock_;
DISALLOW_COPY_AND_ASSIGN(Profiler);
};
// Starts an event on construction and stops it on destruction.
// Used by PROFILE macro.
class ProfilerScope {
public:
explicit ProfilerScope(const std::string& event_name)
: event_name_(event_name) {
Profiler::Instance()->StartEvent(event_name_);
}
~ProfilerScope() {
Profiler::Instance()->StopEvent(event_name_);
}
private:
std::string event_name_;
DISALLOW_COPY_AND_ASSIGN(ProfilerScope);
};
std::ostream& operator<<(std::ostream& stream,
const ProfilerEvent& profiler_event);
} // namespace rtc
#endif // WEBRTC_BASE_PROFILER_H_