blob: 80098eef8196bdeb76958e0338d86ebb6b183926 [file] [log] [blame]
// 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_