blob: e682ffce2374c5ccf4d0980307c543b250c5bf6c [file] [log] [blame]
// 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.
// 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_TIME_MEASUREMENTS_
#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_
#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "components/subresource_filter/core/common/scoped_timers.h"
namespace subresource_filter {
// 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_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) \
auto scoped_uma_histogram_timer_##suffix = \
impl::ScopedTimerImplFactory<time_provider>::Start( \
histogram_exporter(histogram_##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 {
// ExportFunctor implementation that puts measurements into a UMA |histogram|.
template <bool is_microsec_precision>
class ExportTimeDeltaToHistogram {
public:
ExportTimeDeltaToHistogram(base::HistogramBase* histogram)
: histogram_(histogram) {}
void operator()(base::TimeDelta duration) {
if (is_microsec_precision)
histogram_->Add(duration.InMicroseconds());
else
histogram_->Add(duration.InMilliseconds());
}
private:
base::HistogramBase* histogram_;
};
using ExportMillisecondsToHistogram = ExportTimeDeltaToHistogram<false>;
using ExportMicrosecondsToHistogram = ExportTimeDeltaToHistogram<true>;
} // namespace impl
} // namespace subresource_filter
#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_