| // Copyright 2018 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef BAZEL_SRC_MAIN_CPP_UTIL_PROFILER_H_ |
| #define BAZEL_SRC_MAIN_CPP_UTIL_PROFILER_H_ |
| |
| #include <stdint.h> // int64_t |
| #include <stdio.h> // printf |
| |
| namespace blaze_util { |
| namespace profiler { |
| |
| // A time duration, measured in some implementation-dependent units. |
| // |
| // Using a struct to wrap int64_t yields a unique type that we can't |
| // accidentally use as a type-synonym of other int64_t types. |
| struct Ticks { |
| int64_t value_; |
| static Ticks Now(); |
| }; |
| |
| // A time duration, measured in microseconds. |
| // |
| // Using a struct to wrap int64_t yields a unique type that we can't |
| // accidentally use as a type-synonym of other int64_t types. |
| struct Duration { |
| int64_t micros_; |
| static Duration FromTicks(const Ticks ticks); |
| }; |
| |
| // Accumulates statistics about a function or some C++ scope. |
| // |
| // Usage: see ScopedTask. |
| // |
| // Records the number of times the scope was entered (the function called) and |
| // the total time spent in there. Prints the statistics in the destructor. |
| class Task { |
| const char* name_; |
| uint64_t calls_; |
| Ticks total_; |
| |
| public: |
| Task(const char* name) : name_(name), calls_(0), total_({0}) {} |
| ~Task(); |
| void AddCall() { calls_++; } |
| void AddTicks(const Ticks t) { total_.value_ += t.value_; } |
| uint64_t GetCalls() const { return calls_; } |
| Duration GetDuration() const { return Duration::FromTicks(total_); } |
| }; |
| |
| // Measures elapsed time. |
| // |
| // Example: |
| // void foo() { |
| // StopWatch s; |
| // ... |
| // s.PrintAndReset("marker 1"); // prints elapsed time since creation |
| // ... |
| // s.PrintAndReset("marker 2"); // prints elapsed time since "marker 1" |
| // ... |
| // s.Reset(); |
| // ... |
| // Ticks t1 = s.Elapsed(); // time since Reset |
| // ... |
| // Ticks t2 = s.Elapsed(); // time since Reset, not since t1 |
| // } |
| // |
| class StopWatch { |
| Ticks start_; |
| |
| public: |
| // Constructor -- it also resets this StopWatch. |
| StopWatch() { start_ = Ticks::Now(); } |
| |
| // Prints elapsed time since last reset, then resets. |
| // |
| // Args: |
| // name: a descriptive name, will be printed in the output |
| void PrintAndReset(const char* name); |
| |
| // Returns the elapsed time since the last reset as `Ticks`. |
| Ticks Elapsed() const { |
| Ticks now = Ticks::Now(); |
| return {now.value_ - start_.value_}; |
| } |
| |
| // Returns the elapsed time since the last reset as `Duration`. |
| Duration ElapsedTime() const { return Duration::FromTicks(Elapsed()); } |
| |
| // Resets this StopWatch to the current time. |
| void Reset() { start_ = Ticks::Now(); } |
| }; |
| |
| // Measures the execution duration of a given C++ scope. |
| // |
| // The constructor records one call of the scope in a `Task` object, and the |
| // destructor records the time spent in the scope in that `Task` object. |
| // |
| // Usage: |
| // create one Task that accumulates the statistics for a given function |
| // or scope, and create one ScopedTask in the beginning of the scope you want |
| // to measure. Every time the scope is entered (the function is called), a |
| // ScopedTask is created, then destructed when the execution leaves the scope. |
| // The destructor then records the statistics in the Task. |
| // |
| // Example: |
| // Task slow_function_stats("slow function"); // d'tor prints stats |
| // |
| // void slow_function() { |
| // ScopedTask prof(&slow_function_stats); |
| // ... |
| // } |
| // |
| class ScopedTask { |
| public: |
| ScopedTask(Task* s) : stat_(s) { stat_->AddCall(); } |
| ~ScopedTask() { stat_->AddTicks(prof_.Elapsed()); } |
| |
| private: |
| Task* stat_; |
| StopWatch prof_; |
| }; |
| |
| } // namespace profiler |
| } // namespace blaze_util |
| |
| #endif // BAZEL_SRC_MAIN_CPP_UTIL_PROFILER_H_ |