| /* |
| * libjingle |
| * Copyright 2013, Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // 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 event"); |
| // DoSomethingAsyncAndThenCall(&Callback); |
| // } |
| // void Callback() { |
| // PROFILE_STOP("My async event"); |
| // // Handle callback. |
| // } |
| |
| #ifndef TALK_BASE_PROFILER_H_ |
| #define TALK_BASE_PROFILER_H_ |
| |
| #include <map> |
| #include <string> |
| |
| #include "talk/base/basictypes.h" |
| #include "talk/base/common.h" |
| #include "talk/base/logging.h" |
| |
| // Profiling could be switched via a build flag, but for now, it's always on. |
| #define ENABLE_PROFILING |
| |
| #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) talk_base::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) \ |
| talk_base::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) \ |
| talk_base::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) talk_base::Profiler::Instance()->StartEvent(msg) |
| #define PROFILE_STOP(msg) talk_base::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 talk_base { |
| |
| // Tracks information for one profiler event. |
| class ProfilerEvent { |
| public: |
| ProfilerEvent(); |
| void Start(); |
| void Stop(); |
| 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() {} |
| |
| std::map<std::string, ProfilerEvent> events_; |
| |
| 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); |
| }; |
| |
| } // namespace talk_base |
| |
| #endif // TALK_BASE_PROFILER_H_ |