| Index: components/subresource_filter/core/common/scoped_timers.h
|
| diff --git a/components/subresource_filter/core/common/scoped_timers.h b/components/subresource_filter/core/common/scoped_timers.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..58a834c29676d83e420a6a2642613682bdf6471e
|
| --- /dev/null
|
| +++ b/components/subresource_filter/core/common/scoped_timers.h
|
| @@ -0,0 +1,248 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// This file provides tools for measuring time intervals and reporting them to
|
| +// UMA histograms or via custom functors. It is possible to measure time both
|
| +// with base::TimeTicks and base::ThreadTicks.
|
| +// WARNING: *UMA_HISTOGRAM_* macros in this file are not thread-safe.
|
| +// See also: "base/metrics/histogram_macros*.h".
|
| +//
|
| +// TODO(pkalinnikov): Consider moving content of this file to "base/metrics/*"
|
| +// after some refactoring. Note that most of the code generated by the macros
|
| +// below is not thread-safe.
|
| +
|
| +#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
|
| +#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
|
| +
|
| +#include <type_traits>
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/time/time.h"
|
| +
|
| +namespace subresource_filter {
|
| +
|
| +// Creates a scoped object that measures its lifetime using base::TimeTicks, and
|
| +// reports the result as base::TimeDelta via provided |export_functor|. The
|
| +// functor is copied if passed in by value.
|
| +//
|
| +// Example:
|
| +// void Function() {
|
| +// auto export_time = [](base::TimeDelta delta) {
|
| +// LOG(INFO) << "Duration: " << delta.InMicroseconds();
|
| +// };
|
| +// SCOPED_TIMER(export_time);
|
| +// ... Useful things happen here ...
|
| +// } // |export_time| will be triggered here.
|
| +//
|
| +// This is recommended for when you want to measure the time it takes for a
|
| +// method/scope to execute, including, possibly, the time spent by the thread on
|
| +// being blocked and/or descheduled.
|
| +#define SCOPED_TIMER(export_functor) \
|
| + IMPL_SCOPED_TIMER_EXPANDER(impl::TimeTicksProvider, export_functor, \
|
| + __COUNTER__)
|
| +
|
| +// Similar to SCOPED_TIMER, but uses base::ThreadTicks for measuring time.
|
| +//
|
| +// This is recommended for when you want to measure the time it takes for a
|
| +// method/scope to do actual work, i.e. excluding the time spent by the thread
|
| +// on being blocked and/or descheduled.
|
| +#define SCOPED_THREAD_TIMER(export_functor) \
|
| + IMPL_SCOPED_TIMER_EXPANDER(impl::ThreadTicksProvider, export_functor, \
|
| + __COUNTER__)
|
| +
|
| +// Creates a scoped object that measures its lifetime using base::ThreadTicks,
|
| +// and reports the result in milliseconds as a UMA statistic to a histogram with
|
| +// the provided |name| which is expected to be a runtime constant. The histogram
|
| +// collects times up to 10 seconds in 50 buckets.
|
| +//
|
| +// Under the hood there is a static base::HistogramBase* pointer initialized
|
| +// right before the scoped object. The pointer is used by a specific
|
| +// |export_functor| passed in to a SCOPED_THREAD_TIMER (see it above).
|
| +//
|
| +// Example:
|
| +// void Function() {
|
| +// SCOPED_UMA_HISTOGRAM_THREAD_TIMER("Component.FunctionTime");
|
| +// ... Useful things happen here ...
|
| +// }
|
| +//
|
| +// WARNING: The generated code is not thread-safe.
|
| +#define SCOPED_UMA_HISTOGRAM_THREAD_TIMER(name) \
|
| + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
|
| + name, impl::ThreadTicksProvider, impl::ExportMillisecondsToHistogram, \
|
| + 10 * 1000, __COUNTER__)
|
| +
|
| +// Similar to SCOPED_UMA_HISTOGRAM_THREAD_TIMER above, but the histogram
|
| +// collects times in microseconds, up to 1 second, and using 50 buckets.
|
| +//
|
| +// WARNING: The generated code is not thread-safe.
|
| +#define SCOPED_UMA_HISTOGRAM_MICRO_THREAD_TIMER(name) \
|
| + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
|
| + name, impl::ThreadTicksProvider, impl::ExportMicrosecondsToHistogram, \
|
| + 1000 * 1000, __COUNTER__)
|
| +
|
| +// Similar to SCOPED_UMA_HISTOGRAM_TIMER in "base/metrics/histogram_macros.h",
|
| +// but the histogram stores times in microseconds, up to 1 second, in 50
|
| +// buckets.
|
| +//
|
| +// WARNING: The generated code is not thread-safe.
|
| +#define SCOPED_UMA_HISTOGRAM_MICRO_TIMER(name) \
|
| + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
|
| + name, impl::TimeTicksProvider, impl::ExportMicrosecondsToHistogram, \
|
| + 1000 * 1000, __COUNTER__)
|
| +
|
| +// Similar to UMA_HISTOGRAM_TIMES in "base/metrics/histogram_macros.h", but
|
| +// the histogram stores times in microseconds, up to 1 second, in 50 buckets.
|
| +//
|
| +// WARNING: The generated code is not thread-safe.
|
| +#define UMA_HISTOGRAM_MICRO_TIMES(name, sample) \
|
| + UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(name, sample, \
|
| + base::TimeDelta::FromMicroseconds(1), \
|
| + base::TimeDelta::FromSeconds(1), 50)
|
| +
|
| +// This can be used when the default ranges are not sufficient. This macro lets
|
| +// the metric developer customize the min and max of the sampled range, as well
|
| +// as the number of buckets recorded.
|
| +#define UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(name, sample, min, max, bucket_count) \
|
| + IMPL_UMA_HISTOGRAM_ADD(name, sample.InMicroseconds(), min.InMicroseconds(), \
|
| + max.InMicroseconds(), bucket_count)
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// Below are helpers used by other macros. Shouldn't be used directly. ---------
|
| +
|
| +// This is necessary to expand __COUNTER__ to an actual value.
|
| +#define IMPL_SCOPED_TIMER_EXPANDER(time_provider, export_functor, suffix) \
|
| + IMPL_SCOPED_TIMER_UNIQUE(time_provider, export_functor, suffix)
|
| +
|
| +// Creates a scoped timer, which uses |time_provider| to measure time, and
|
| +// |export_functor| to report it.
|
| +#define IMPL_SCOPED_TIMER_UNIQUE(time_provider, export_functor, suffix) \
|
| + impl::ScopedTimer<time_provider, decltype(export_functor)> \
|
| + scoped_timer_##suffix(export_functor);
|
| +
|
| +// This is necessary to expand __COUNTER__ to an actual value.
|
| +#define IMPL_SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER( \
|
| + name, time_provider, histogram_exporter, max_value, suffix) \
|
| + IMPL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE( \
|
| + name, time_provider, histogram_exporter, max_value, suffix)
|
| +
|
| +// Creates a static histogram pointer and a scoped object referring to it
|
| +// throught the |histogram_exporter| functor. Both the pointer and the scoped
|
| +// object are uniquely-named, using the unique |suffix| passed in.
|
| +#define IMPL_SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE( \
|
| + name, time_provider, histogram_exporter, max_value, suffix) \
|
| + IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, 1, max_value, 50, suffix) \
|
| + IMPL_SCOPED_TIMER_UNIQUE(time_provider, \
|
| + (histogram_exporter(histogram_##suffix)), suffix)
|
| +
|
| +// This is necessary to expand __COUNTER__ to an actual value.
|
| +#define IMPL_UMA_HISTOGRAM_MICRO_TIMES_EXPANDER(name, max_value, suffix, \
|
| + sample) \
|
| + IMPL_UMA_HISTOGRAM_MICRO_TIMES_UNIQUE(name, max_value, suffix, sample)
|
| +
|
| +// Defines a static UMA histogram pointer and writes a |sample| to it.
|
| +#define IMPL_UMA_HISTOGRAM_ADD(name, sample, min, max, bucket_count) \
|
| + do { \
|
| + IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, min, max, bucket_count, 0) \
|
| + histogram_0->Add(sample); \
|
| + } while (0)
|
| +
|
| +// Defines a static pointer to a UMA histogram.
|
| +//
|
| +// WARNING: Static local variable initialization is deliberately *not*
|
| +// thread-safe in Chrome builds. See the "-fno-threadsafe-statics" flag in
|
| +// "build/config/compiler/BUILD.gn" and "/Zc:threadSafeInit-" in
|
| +// "build/config/win/BUILD.gn" for details.
|
| +#define IMPL_DEFINE_STATIC_UMA_HISTOGRAM_POINTER(name, min, max, bucket_count, \
|
| + suffix) \
|
| + static base::HistogramBase* histogram_##suffix = \
|
| + base::Histogram::FactoryGet( \
|
| + name, min, max, bucket_count, \
|
| + base::HistogramBase::kUmaTargetedHistogramFlag);
|
| +
|
| +namespace impl {
|
| +
|
| +// ScopedTimer is a multi-purpose scoped timer. It measures time delta from its
|
| +// construction till destruction. For example, by putting an instance of this
|
| +// class to the beginning of a scope it is possible to measure how long the
|
| +// scope is being executed.
|
| +//
|
| +// The obtained time measurement is reported via ExportFunctor, which takes
|
| +// base::TimeDelta as a parameter.
|
| +//
|
| +// Time is obtained by means of the TimeProvider static interface:
|
| +// * static bool IsSupported();
|
| +// - Idempotently returns whether the system supports such type of provider.
|
| +// * static void WaitUntilInitialized();
|
| +// - Waits until the provider can be used.
|
| +// * static TimeType Now();
|
| +// - Returns the current time of some TimeType, e.g., base::TimeTicks.
|
| +//
|
| +// Time measurement is exported exactly once, unless TimeProvider::IsSupported()
|
| +// is false. In the latter case ExportFunctor is never called.
|
| +template <typename TimeProvider, typename ExportFunctor>
|
| +class ScopedTimer {
|
| + public:
|
| + ScopedTimer(ExportFunctor export_functor) : export_functor_(export_functor) {
|
| + if (TimeProvider::IsSupported()) {
|
| + TimeProvider::WaitUntilInitialized();
|
| + construction_time_ = TimeProvider::Now();
|
| + }
|
| + }
|
| +
|
| + ~ScopedTimer() {
|
| + if (TimeProvider::IsSupported()) {
|
| + const base::TimeDelta delta = TimeProvider::Now() - construction_time_;
|
| + export_functor_(delta);
|
| + }
|
| + }
|
| +
|
| + private:
|
| + using TimeType =
|
| + typename std::remove_reference<decltype(TimeProvider::Now())>::type;
|
| +
|
| + ExportFunctor export_functor_;
|
| + TimeType construction_time_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ScopedTimer);
|
| +};
|
| +
|
| +// TimeProvider implementations ------------------------------------------------
|
| +
|
| +class TimeTicksProvider {
|
| + public:
|
| + static bool IsSupported() { return true; }
|
| + static void WaitUntilInitialized() {}
|
| + static base::TimeTicks Now() { return base::TimeTicks::Now(); }
|
| +};
|
| +
|
| +using ThreadTicksProvider = base::ThreadTicks;
|
| +
|
| +// ExportFunctor implementations -----------------------------------------------
|
| +
|
| +template <bool is_microsec_precision>
|
| +class ExportTimeDeltaToHistogram {
|
| + public:
|
| + ExportTimeDeltaToHistogram(base::HistogramBase* histogram)
|
| + : histogram_(histogram) {}
|
| +
|
| + void operator()(base::TimeDelta delta) {
|
| + if (is_microsec_precision)
|
| + histogram_->Add(delta.InMicroseconds());
|
| + else
|
| + histogram_->Add(delta.InMilliseconds());
|
| + }
|
| +
|
| + private:
|
| + base::HistogramBase* histogram_;
|
| +};
|
| +
|
| +using ExportMillisecondsToHistogram = ExportTimeDeltaToHistogram<false>;
|
| +using ExportMicrosecondsToHistogram = ExportTimeDeltaToHistogram<true>;
|
| +
|
| +} // namespace impl
|
| +
|
| +} // namespace subresource_filter
|
| +
|
| +#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
|
|
|