diff options
Diffstat (limited to 'src/main/cpp/util/profiler.h')
-rw-r--r-- | src/main/cpp/util/profiler.h | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/main/cpp/util/profiler.h b/src/main/cpp/util/profiler.h new file mode 100644 index 0000000000..80098eef81 --- /dev/null +++ b/src/main/cpp/util/profiler.h @@ -0,0 +1,138 @@ +// 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_ |