Bump to WebRTC M120 release
Some API deprecation -- ExperimentalAgc and ExperimentalNs are gone. We're continuing to carry iSAC even though it's gone upstream, but maybe we'll want to drop that soon.
This commit is contained in:
@ -36,8 +36,10 @@ rtc_library("system_wrappers") {
|
||||
"../api/units:timestamp",
|
||||
"../modules:module_api_public",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:safe_conversions",
|
||||
"../rtc_base:timeutils",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
"../rtc_base/synchronization:rw_lock_wrapper",
|
||||
"../rtc_base/system:arch",
|
||||
"../rtc_base/system:rtc_export",
|
||||
]
|
||||
@ -52,7 +54,7 @@ rtc_library("system_wrappers") {
|
||||
]
|
||||
} else {
|
||||
sources += [ "source/cpu_features_android.cc" ]
|
||||
deps += [ "//third_party/android_sdk:cpu_features" ]
|
||||
deps += [ "//third_party/cpu_features:ndk_compat" ]
|
||||
}
|
||||
|
||||
libs += [ "log" ]
|
||||
@ -74,10 +76,7 @@ rtc_library("system_wrappers") {
|
||||
deps += [ "../rtc_base:win32" ]
|
||||
}
|
||||
|
||||
deps += [
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_numerics",
|
||||
]
|
||||
deps += [ "../rtc_base:rtc_numerics" ]
|
||||
}
|
||||
|
||||
rtc_library("field_trial") {
|
||||
@ -88,11 +87,16 @@ rtc_library("field_trial") {
|
||||
defines = [ "WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT" ]
|
||||
}
|
||||
deps = [
|
||||
"../experiments:registered_field_trials",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base/containers:flat_set",
|
||||
]
|
||||
absl_deps = [
|
||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
|
||||
}
|
||||
|
||||
rtc_library("metrics") {
|
||||
@ -104,16 +108,32 @@ rtc_library("metrics") {
|
||||
}
|
||||
deps = [
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:macromagic",
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_library("denormal_disabler") {
|
||||
visibility = [ "*" ]
|
||||
public = [ "include/denormal_disabler.h" ]
|
||||
sources = [ "source/denormal_disabler.cc" ]
|
||||
deps = [
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/system:arch",
|
||||
]
|
||||
if (is_clang) {
|
||||
cflags_cc = [ "-Wno-unused-private-field" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_include_tests && !build_with_chromium) {
|
||||
rtc_test("system_wrappers_unittests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"source/clock_unittest.cc",
|
||||
"source/denormal_disabler_unittest.cc",
|
||||
"source/field_trial_unittest.cc",
|
||||
"source/metrics_default_unittest.cc",
|
||||
"source/metrics_unittest.cc",
|
||||
@ -122,18 +142,21 @@ if (rtc_include_tests) {
|
||||
]
|
||||
|
||||
deps = [
|
||||
":denormal_disabler",
|
||||
":field_trial",
|
||||
":metrics",
|
||||
":system_wrappers",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:random",
|
||||
"../rtc_base:stringutils",
|
||||
"../test:rtc_expect_death",
|
||||
"../test:test_main",
|
||||
"../test:test_support",
|
||||
"//testing/gtest",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
]
|
||||
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
// List of features in x86.
|
||||
typedef enum { kSSE2, kSSE3, kAVX2 } CPUFeature;
|
||||
typedef enum { kSSE2, kSSE3, kAVX2, kFMA3 } CPUFeature;
|
||||
|
||||
// List of features in ARM.
|
||||
enum {
|
||||
|
56
webrtc/system_wrappers/include/denormal_disabler.h
Normal file
56
webrtc/system_wrappers/include/denormal_disabler.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
||||
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Activates the hardware (HW) way to flush denormals (see [1]) to zero as they
|
||||
// can very seriously impact performance. At destruction time restores the
|
||||
// denormals handling state read by the ctor; hence, supports nested calls.
|
||||
// Equals a no-op if the architecture is not x86 or ARM or if the compiler is
|
||||
// not CLANG.
|
||||
// [1] https://en.wikipedia.org/wiki/Denormal_number
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// void Foo() {
|
||||
// DenormalDisabler d;
|
||||
// ...
|
||||
// }
|
||||
class DenormalDisabler {
|
||||
public:
|
||||
// Ctor. If architecture and compiler are supported, stores the HW settings
|
||||
// for denormals, disables denormals and sets `disabling_activated_` to true.
|
||||
// Otherwise, only sets `disabling_activated_` to false.
|
||||
DenormalDisabler();
|
||||
// Ctor. Same as above, but also requires `enabled` to be true to disable
|
||||
// denormals.
|
||||
explicit DenormalDisabler(bool enabled);
|
||||
DenormalDisabler(const DenormalDisabler&) = delete;
|
||||
DenormalDisabler& operator=(const DenormalDisabler&) = delete;
|
||||
// Dtor. If `disabling_activated_` is true, restores the denormals HW settings
|
||||
// read by the ctor before denormals were disabled. Otherwise it's a no-op.
|
||||
~DenormalDisabler();
|
||||
|
||||
// Returns true if architecture and compiler are supported.
|
||||
static bool IsSupported();
|
||||
|
||||
private:
|
||||
const int status_word_;
|
||||
const bool disabling_activated_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
@ -13,6 +13,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/containers/flat_set.h"
|
||||
|
||||
// Field trials allow webrtc clients (such as Chrome) to turn on feature code
|
||||
// in binaries out in the field and gather information with that.
|
||||
//
|
||||
@ -24,7 +27,7 @@
|
||||
// WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT (if GN is used this can be achieved
|
||||
// by setting the GN arg rtc_exclude_field_trial_default to true).
|
||||
// 2. Provide an implementation of:
|
||||
// std::string webrtc::field_trial::FindFullName(const std::string& trial).
|
||||
// std::string webrtc::field_trial::FindFullName(absl::string_view trial).
|
||||
//
|
||||
// They are designed to wire up directly to chrome field trials and to speed up
|
||||
// developers by reducing the need to wire APIs to control whether a feature is
|
||||
@ -61,18 +64,18 @@ namespace field_trial {
|
||||
// if the trial does not exists.
|
||||
//
|
||||
// Note: To keep things tidy append all the trial names with WebRTC.
|
||||
std::string FindFullName(const std::string& name);
|
||||
std::string FindFullName(absl::string_view name);
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Enabled".
|
||||
// TODO(tommi): Make sure all implementations support this.
|
||||
inline bool IsEnabled(const char* name) {
|
||||
inline bool IsEnabled(absl::string_view name) {
|
||||
return FindFullName(name).find("Enabled") == 0;
|
||||
}
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Disabled".
|
||||
inline bool IsDisabled(const char* name) {
|
||||
inline bool IsDisabled(absl::string_view name) {
|
||||
return FindFullName(name).find("Disabled") == 0;
|
||||
}
|
||||
|
||||
@ -84,17 +87,28 @@ void InitFieldTrialsFromString(const char* trials_string);
|
||||
|
||||
const char* GetFieldTrialString();
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
// Validates the given field trial string.
|
||||
bool FieldTrialsStringIsValid(const char* trials_string);
|
||||
bool FieldTrialsStringIsValid(absl::string_view trials_string);
|
||||
|
||||
// Merges two field trial strings.
|
||||
//
|
||||
// If a key (trial) exists twice with conflicting values (groups), the value
|
||||
// in 'second' takes precedence.
|
||||
// Shall only be called with valid FieldTrial strings.
|
||||
std::string MergeFieldTrialsStrings(const char* first, const char* second);
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
std::string MergeFieldTrialsStrings(absl::string_view first,
|
||||
absl::string_view second);
|
||||
|
||||
// This helper allows to temporary "register" a field trial within the current
|
||||
// scope. This is only useful for tests that use the global field trial string,
|
||||
// otherwise you can use `webrtc::FieldTrialsRegistry`.
|
||||
//
|
||||
// If you want to isolate changes to the global field trial string itself within
|
||||
// the current scope you should use `webrtc::test::ScopedFieldTrials`.
|
||||
class FieldTrialsAllowedInScopeForTesting {
|
||||
public:
|
||||
explicit FieldTrialsAllowedInScopeForTesting(flat_set<std::string> keys);
|
||||
~FieldTrialsAllowedInScopeForTesting();
|
||||
};
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
|
@ -13,12 +13,14 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/atomic_ops.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/string_utils.h"
|
||||
|
||||
#if defined(RTC_DISABLE_METRICS)
|
||||
#define RTC_METRICS_ENABLED 0
|
||||
@ -30,8 +32,8 @@ namespace webrtc {
|
||||
namespace metrics_impl {
|
||||
template <typename... Ts>
|
||||
void NoOp(const Ts&...) {}
|
||||
}
|
||||
}
|
||||
} // namespace metrics_impl
|
||||
} // namespace webrtc
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
#define EXPECT_METRIC_EQ(val1, val2) EXPECT_EQ(val1, val2)
|
||||
@ -44,12 +46,16 @@ void NoOp(const Ts&...) {}
|
||||
#define EXPECT_METRIC_THAT(value, matcher) EXPECT_THAT(value, matcher)
|
||||
#else
|
||||
#define EXPECT_METRIC_EQ(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) webrtc::metrics_impl::NoOp(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) \
|
||||
webrtc::metrics_impl::NoOp(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_GT(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_LE(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_TRUE(condition) webrtc::metrics_impl::NoOp(condition || true)
|
||||
#define EXPECT_METRIC_FALSE(condition) webrtc::metrics_impl::NoOp(condition && false)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) webrtc::metrics_impl::NoOp(value, testing::_)
|
||||
#define EXPECT_METRIC_TRUE(condition) \
|
||||
webrtc::metrics_impl::NoOp(condition || true)
|
||||
#define EXPECT_METRIC_FALSE(condition) \
|
||||
webrtc::metrics_impl::NoOp(condition && false)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) \
|
||||
webrtc::metrics_impl::NoOp(value, testing::_)
|
||||
#endif
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
@ -76,12 +82,12 @@ void NoOp(const Ts&...) {}
|
||||
// by setting the GN arg rtc_exclude_metrics_default to true).
|
||||
// 2. Provide implementations of:
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetCounts(
|
||||
// const std::string& name, int sample, int min, int max,
|
||||
// absl::string_view name, int sample, int min, int max,
|
||||
// int bucket_count);
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetEnumeration(
|
||||
// const std::string& name, int sample, int boundary);
|
||||
// absl::string_view name, int sample, int boundary);
|
||||
// void webrtc::metrics::HistogramAdd(
|
||||
// Histogram* histogram_pointer, const std::string& name, int sample);
|
||||
// Histogram* histogram_pointer, absl::string_view name, int sample);
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
@ -163,7 +169,7 @@ void NoOp(const Ts&...) {}
|
||||
RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
//
|
||||
// TODO(qingsi): Refactor the default implementation given by RtcHistogram,
|
||||
// which is already sparse, and remove the boundary argument from the macro.
|
||||
@ -181,33 +187,29 @@ void NoOp(const Ts&...) {}
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
|
||||
name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
|
||||
|
||||
// The name of the histogram should not vary.
|
||||
// TODO(asapersson): Consider changing string to const char*.
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
do { \
|
||||
static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \
|
||||
webrtc::metrics::Histogram* histogram_pointer = \
|
||||
rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \
|
||||
if (!histogram_pointer) { \
|
||||
histogram_pointer = factory_get_invocation; \
|
||||
webrtc::metrics::Histogram* prev_pointer = \
|
||||
rtc::AtomicOps::CompareAndSwapPtr( \
|
||||
&atomic_histogram_pointer, \
|
||||
static_cast<webrtc::metrics::Histogram*>(nullptr), \
|
||||
histogram_pointer); \
|
||||
RTC_DCHECK(prev_pointer == nullptr || \
|
||||
prev_pointer == histogram_pointer); \
|
||||
} \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
do { \
|
||||
static std::atomic<webrtc::metrics::Histogram*> atomic_histogram_pointer( \
|
||||
nullptr); \
|
||||
webrtc::metrics::Histogram* histogram_pointer = \
|
||||
atomic_histogram_pointer.load(std::memory_order_acquire); \
|
||||
if (!histogram_pointer) { \
|
||||
histogram_pointer = factory_get_invocation; \
|
||||
webrtc::metrics::Histogram* null_histogram = nullptr; \
|
||||
atomic_histogram_pointer.compare_exchange_strong(null_histogram, \
|
||||
histogram_pointer); \
|
||||
} \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// The histogram is constructed/found for each call.
|
||||
@ -223,7 +225,7 @@ void NoOp(const Ts&...) {}
|
||||
// Helper macros.
|
||||
// Macros for calling a histogram with varying name (e.g. when using a metric
|
||||
// in different modes such as real-time vs screenshare). Fast, because pointer
|
||||
// is cached. |index| should be different for different names. Allowed |index|
|
||||
// is cached. `index` should be different for different names. Allowed `index`
|
||||
// values are 0, 1, and 2.
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
@ -270,7 +272,7 @@ void NoOp(const Ts&...) {}
|
||||
macro_invocation; \
|
||||
break; \
|
||||
default: \
|
||||
RTC_NOTREACHED(); \
|
||||
RTC_DCHECK_NOTREACHED(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -280,17 +282,23 @@ void NoOp(const Ts&...) {}
|
||||
// This section defines no-op alternatives to the metrics macros when
|
||||
// RTC_METRICS_ENABLED is defined.
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
@ -298,31 +306,41 @@ void NoOp(const Ts&...) {}
|
||||
#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) webrtc::metrics_impl::NoOp(name, sample)
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
@ -334,11 +352,14 @@ void NoOp(const Ts&...) {}
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, factory_get_invocation)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
@ -352,7 +373,8 @@ void NoOp(const Ts&...) {}
|
||||
#define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, macro_invocation)
|
||||
@ -363,7 +385,7 @@ namespace webrtc {
|
||||
namespace metrics {
|
||||
|
||||
// Time that should have elapsed for stats that are gathered once per call.
|
||||
enum { kMinRunTimeInSeconds = 10 };
|
||||
constexpr int kMinRunTimeInSeconds = 10;
|
||||
|
||||
class Histogram;
|
||||
|
||||
@ -371,32 +393,31 @@ class Histogram;
|
||||
// histogram).
|
||||
|
||||
// Get histogram for counters.
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
Histogram* HistogramFactoryGetCounts(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for counters with linear bucket spacing.
|
||||
Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
Histogram* HistogramFactoryGetCountsLinear(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for enumerators.
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
int boundary);
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
Histogram* HistogramFactoryGetEnumeration(absl::string_view name, int boundary);
|
||||
|
||||
// Get sparse histogram for enumerators.
|
||||
// |boundary| should be above the max enumerator sample.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary);
|
||||
|
||||
// Function for adding a |sample| to a histogram.
|
||||
// Function for adding a `sample` to a histogram.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample);
|
||||
|
||||
struct SampleInfo {
|
||||
SampleInfo(const std::string& name, int min, int max, size_t bucket_count);
|
||||
SampleInfo(absl::string_view name, int min, int max, size_t bucket_count);
|
||||
~SampleInfo();
|
||||
|
||||
const std::string name;
|
||||
@ -412,25 +433,26 @@ void Enable();
|
||||
|
||||
// Gets histograms and clears all samples.
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms);
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>, rtc::AbslStringViewCmp>*
|
||||
histograms);
|
||||
|
||||
// Functions below are mainly for testing.
|
||||
|
||||
// Clears all samples.
|
||||
void Reset();
|
||||
|
||||
// Returns the number of times the |sample| has been added to the histogram.
|
||||
int NumEvents(const std::string& name, int sample);
|
||||
// Returns the number of times the `sample` has been added to the histogram.
|
||||
int NumEvents(absl::string_view name, int sample);
|
||||
|
||||
// Returns the total number of added samples to the histogram.
|
||||
int NumSamples(const std::string& name);
|
||||
int NumSamples(absl::string_view name);
|
||||
|
||||
// Returns the minimum sample value (or -1 if the histogram has no samples).
|
||||
int MinSample(const std::string& name);
|
||||
int MinSample(absl::string_view name);
|
||||
|
||||
// Returns a map with keys the samples with at least one event and values the
|
||||
// number of events for that sample.
|
||||
std::map<int, int> Samples(const std::string& name);
|
||||
std::map<int, int> Samples(absl::string_view name);
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
@ -1,5 +1,6 @@
|
||||
system_wrappers_sources = [
|
||||
'source/cpu_features.cc',
|
||||
'source/denormal_disabler.cc',
|
||||
'source/field_trial.cc',
|
||||
'source/metrics.cc',
|
||||
'source/sleep.cc',
|
||||
|
@ -30,7 +30,7 @@ int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
// xgetbv returns the value of an Intel Extended Control Register (XCR).
|
||||
// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
|
||||
// Currently only XCR0 is defined by Intel so `xcr` should always be zero.
|
||||
static uint64_t xgetbv(uint32_t xcr) {
|
||||
#if defined(_MSC_VER)
|
||||
return _xgetbv(xcr);
|
||||
@ -93,15 +93,19 @@ int GetCPUInfo(CPUFeature feature) {
|
||||
// a) AVX are supported by the CPU,
|
||||
// b) XSAVE is supported by the CPU,
|
||||
// c) XSAVE is enabled by the kernel.
|
||||
// See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
|
||||
// AVX2 support needs (avx_support && (cpu_info7[1] & 0x00000020) != 0;).
|
||||
return (cpu_info[2] & 0x10000000) != 0 &&
|
||||
// Compiling with MSVC and /arch:AVX2 surprisingly generates BMI2
|
||||
// instructions (see crbug.com/1315519).
|
||||
return (cpu_info[2] & 0x10000000) != 0 /* AVX */ &&
|
||||
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
|
||||
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
|
||||
(xgetbv(0) & 0x00000006) == 6 /* XSAVE enabled by kernel */ &&
|
||||
(cpu_info7[1] & 0x00000020) != 0;
|
||||
(cpu_info7[1] & 0x00000020) != 0 /* AVX2 */ &&
|
||||
(cpu_info7[1] & 0x00000100) != 0 /* BMI2 */;
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
if (feature == kFMA3) {
|
||||
return 0 != (cpu_info[2] & 0x00001000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
111
webrtc/system_wrappers/source/denormal_disabler.cc
Normal file
111
webrtc/system_wrappers/source/denormal_disabler.cc
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "system_wrappers/include/denormal_disabler.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(__clang__)
|
||||
#define WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED) || \
|
||||
defined(WEBRTC_ARCH_ARM_FAMILY)
|
||||
#define WEBRTC_DENORMAL_DISABLER_SUPPORTED
|
||||
#endif
|
||||
|
||||
constexpr int kUnspecifiedStatusWord = -1;
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
|
||||
// Control register bit mask to disable denormals on the hardware.
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
// On x86 two bits are used: flush-to-zero (FTZ) and denormals-are-zero (DAZ).
|
||||
constexpr int kDenormalBitMask = 0x8040;
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY)
|
||||
// On ARM one bit is used: flush-to-zero (FTZ).
|
||||
constexpr int kDenormalBitMask = 1 << 24;
|
||||
#endif
|
||||
|
||||
// Reads the relevant CPU control register and returns its value for supported
|
||||
// architectures and compilers. Otherwise returns `kUnspecifiedStatusWord`.
|
||||
int ReadStatusWord() {
|
||||
int result = kUnspecifiedStatusWord;
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
asm volatile("stmxcsr %0" : "=m"(result));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_32_BITS)
|
||||
asm volatile("vmrs %[result], FPSCR" : [result] "=r"(result));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_64_BITS)
|
||||
asm volatile("mrs %x[result], FPCR" : [result] "=r"(result));
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// Writes `status_word` in the relevant CPU control register if the architecture
|
||||
// and the compiler are supported.
|
||||
void SetStatusWord(int status_word) {
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
asm volatile("ldmxcsr %0" : : "m"(status_word));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_32_BITS)
|
||||
asm volatile("vmsr FPSCR, %[src]" : : [src] "r"(status_word));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_64_BITS)
|
||||
asm volatile("msr FPCR, %x[src]" : : [src] "r"(status_word));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns true if the status word indicates that denormals are enabled.
|
||||
constexpr bool DenormalsEnabled(int status_word) {
|
||||
return (status_word & kDenormalBitMask) != kDenormalBitMask;
|
||||
}
|
||||
|
||||
#endif // defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
DenormalDisabler::DenormalDisabler() : DenormalDisabler(/*enabled=*/true) {}
|
||||
|
||||
DenormalDisabler::DenormalDisabler(bool enabled)
|
||||
: status_word_(enabled ? ReadStatusWord() : kUnspecifiedStatusWord),
|
||||
disabling_activated_(enabled && DenormalsEnabled(status_word_)) {
|
||||
if (disabling_activated_) {
|
||||
RTC_DCHECK_NE(status_word_, kUnspecifiedStatusWord);
|
||||
SetStatusWord(status_word_ | kDenormalBitMask);
|
||||
RTC_DCHECK(!DenormalsEnabled(ReadStatusWord()));
|
||||
}
|
||||
}
|
||||
|
||||
bool DenormalDisabler::IsSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
DenormalDisabler::~DenormalDisabler() {
|
||||
if (disabling_activated_) {
|
||||
RTC_DCHECK_NE(status_word_, kUnspecifiedStatusWord);
|
||||
SetStatusWord(status_word_);
|
||||
}
|
||||
}
|
||||
#else
|
||||
DenormalDisabler::DenormalDisabler() : DenormalDisabler(/*enabled=*/false) {}
|
||||
|
||||
DenormalDisabler::DenormalDisabler(bool enabled)
|
||||
: status_word_(kUnspecifiedStatusWord), disabling_activated_(false) {}
|
||||
|
||||
bool DenormalDisabler::IsSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DenormalDisabler::~DenormalDisabler() = default;
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
@ -13,9 +13,13 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "experiments/registered_field_trials.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/containers/flat_set.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
|
||||
@ -26,9 +30,15 @@ namespace field_trial {
|
||||
|
||||
static const char* trials_init_string = NULL;
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
namespace {
|
||||
|
||||
constexpr char kPersistentStringSeparator = '/';
|
||||
|
||||
flat_set<std::string>& TestKeys() {
|
||||
static auto* test_keys = new flat_set<std::string>();
|
||||
return *test_keys;
|
||||
}
|
||||
|
||||
// Validates the given field trial string.
|
||||
// E.g.:
|
||||
// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
|
||||
@ -68,9 +78,10 @@ bool FieldTrialsStringIsValidInternal(const absl::string_view trials) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool FieldTrialsStringIsValid(const char* trials_string) {
|
||||
bool FieldTrialsStringIsValid(absl::string_view trials_string) {
|
||||
return FieldTrialsStringIsValidInternal(trials_string);
|
||||
}
|
||||
|
||||
@ -78,18 +89,19 @@ void InsertOrReplaceFieldTrialStringsInMap(
|
||||
std::map<std::string, std::string>* fieldtrial_map,
|
||||
const absl::string_view trials_string) {
|
||||
if (FieldTrialsStringIsValidInternal(trials_string)) {
|
||||
std::vector<std::string> tokens;
|
||||
rtc::split(std::string(trials_string), '/', &tokens);
|
||||
std::vector<absl::string_view> tokens = rtc::split(trials_string, '/');
|
||||
// Skip last token which is empty due to trailing '/'.
|
||||
for (size_t idx = 0; idx < tokens.size() - 1; idx += 2) {
|
||||
(*fieldtrial_map)[tokens[idx]] = tokens[idx + 1];
|
||||
(*fieldtrial_map)[std::string(tokens[idx])] =
|
||||
std::string(tokens[idx + 1]);
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK(false) << "Invalid field trials string:" << trials_string;
|
||||
RTC_DCHECK_NOTREACHED() << "Invalid field trials string:" << trials_string;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MergeFieldTrialsStrings(const char* first, const char* second) {
|
||||
std::string MergeFieldTrialsStrings(absl::string_view first,
|
||||
absl::string_view second) {
|
||||
std::map<std::string, std::string> fieldtrial_map;
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, first);
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, second);
|
||||
@ -102,11 +114,23 @@ std::string MergeFieldTrialsStrings(const char* first, const char* second) {
|
||||
return merged;
|
||||
}
|
||||
|
||||
std::string FindFullName(const std::string& name) {
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
std::string FindFullName(absl::string_view name) {
|
||||
#if WEBRTC_STRICT_FIELD_TRIALS == 1
|
||||
RTC_DCHECK(absl::c_linear_search(kRegisteredFieldTrials, name) ||
|
||||
TestKeys().contains(name))
|
||||
<< name << " is not registered, see g3doc/field-trials.md.";
|
||||
#elif WEBRTC_STRICT_FIELD_TRIALS == 2
|
||||
RTC_LOG_IF(LS_WARNING,
|
||||
!(absl::c_linear_search(kRegisteredFieldTrials, name) ||
|
||||
TestKeys().contains(name)))
|
||||
<< name << " is not registered, see g3doc/field-trials.md.";
|
||||
#endif
|
||||
|
||||
if (trials_init_string == NULL)
|
||||
return std::string();
|
||||
|
||||
std::string trials_string(trials_init_string);
|
||||
absl::string_view trials_string(trials_init_string);
|
||||
if (trials_string.empty())
|
||||
return std::string();
|
||||
|
||||
@ -122,14 +146,14 @@ std::string FindFullName(const std::string& name) {
|
||||
if (field_value_end == trials_string.npos ||
|
||||
field_value_end == field_name_end + 1)
|
||||
break;
|
||||
std::string field_name(trials_string, next_item,
|
||||
field_name_end - next_item);
|
||||
std::string field_value(trials_string, field_name_end + 1,
|
||||
field_value_end - field_name_end - 1);
|
||||
absl::string_view field_name =
|
||||
trials_string.substr(next_item, field_name_end - next_item);
|
||||
absl::string_view field_value = trials_string.substr(
|
||||
field_name_end + 1, field_value_end - field_name_end - 1);
|
||||
next_item = field_value_end + 1;
|
||||
|
||||
if (name == field_name)
|
||||
return field_value;
|
||||
return std::string(field_value);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
@ -138,12 +162,10 @@ std::string FindFullName(const std::string& name) {
|
||||
// Optionally initialize field trial from a string.
|
||||
void InitFieldTrialsFromString(const char* trials_string) {
|
||||
RTC_LOG(LS_INFO) << "Setting field trial string:" << trials_string;
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
if (trials_string) {
|
||||
RTC_DCHECK(FieldTrialsStringIsValidInternal(trials_string))
|
||||
<< "Invalid field trials string:" << trials_string;
|
||||
};
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
trials_init_string = trials_string;
|
||||
}
|
||||
|
||||
@ -151,5 +173,14 @@ const char* GetFieldTrialString() {
|
||||
return trials_init_string;
|
||||
}
|
||||
|
||||
FieldTrialsAllowedInScopeForTesting::FieldTrialsAllowedInScopeForTesting(
|
||||
flat_set<std::string> keys) {
|
||||
TestKeys() = std::move(keys);
|
||||
}
|
||||
|
||||
FieldTrialsAllowedInScopeForTesting::~FieldTrialsAllowedInScopeForTesting() {
|
||||
TestKeys().clear();
|
||||
}
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
|
@ -11,7 +11,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/string_utils.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
@ -30,11 +31,14 @@ const int kMaxSampleMapSize = 300;
|
||||
|
||||
class RtcHistogram {
|
||||
public:
|
||||
RtcHistogram(const std::string& name, int min, int max, int bucket_count)
|
||||
RtcHistogram(absl::string_view name, int min, int max, int bucket_count)
|
||||
: min_(min), max_(max), info_(name, min, max, bucket_count) {
|
||||
RTC_DCHECK_GT(bucket_count, 0);
|
||||
}
|
||||
|
||||
RtcHistogram(const RtcHistogram&) = delete;
|
||||
RtcHistogram& operator=(const RtcHistogram&) = delete;
|
||||
|
||||
void Add(int sample) {
|
||||
sample = std::min(sample, max_);
|
||||
sample = std::max(sample, min_ - 1); // Underflow bucket.
|
||||
@ -99,8 +103,6 @@ class RtcHistogram {
|
||||
const int min_;
|
||||
const int max_;
|
||||
SampleInfo info_ RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogram);
|
||||
};
|
||||
|
||||
class RtcHistogramMap {
|
||||
@ -108,7 +110,10 @@ class RtcHistogramMap {
|
||||
RtcHistogramMap() {}
|
||||
~RtcHistogramMap() {}
|
||||
|
||||
Histogram* GetCountsHistogram(const std::string& name,
|
||||
RtcHistogramMap(const RtcHistogramMap&) = delete;
|
||||
RtcHistogramMap& operator=(const RtcHistogramMap&) = delete;
|
||||
|
||||
Histogram* GetCountsHistogram(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
@ -118,23 +123,24 @@ class RtcHistogramMap {
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, min, max, bucket_count);
|
||||
map_[name].reset(hist);
|
||||
map_.emplace(name, hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
Histogram* GetEnumerationHistogram(const std::string& name, int boundary) {
|
||||
Histogram* GetEnumerationHistogram(absl::string_view name, int boundary) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, 1, boundary, boundary + 1);
|
||||
map_[name].reset(hist);
|
||||
map_.emplace(name, hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
void GetAndReset(std::map<std::string,
|
||||
std::unique_ptr<SampleInfo>,
|
||||
rtc::AbslStringViewCmp>* histograms) {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_) {
|
||||
std::unique_ptr<SampleInfo> info = kv.second->GetAndReset();
|
||||
@ -150,25 +156,25 @@ class RtcHistogramMap {
|
||||
kv.second->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) const {
|
||||
int NumEvents(absl::string_view name, int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumEvents(sample);
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) const {
|
||||
int NumSamples(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumSamples();
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) const {
|
||||
int MinSample(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? -1 : it->second->MinSample();
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) const {
|
||||
std::map<int, int> Samples(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? std::map<int, int>() : it->second->Samples();
|
||||
@ -176,25 +182,21 @@ class RtcHistogramMap {
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
std::map<std::string, std::unique_ptr<RtcHistogram>> map_
|
||||
RTC_GUARDED_BY(mutex_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogramMap);
|
||||
std::map<std::string, std::unique_ptr<RtcHistogram>, rtc::AbslStringViewCmp>
|
||||
map_ RTC_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
// RtcHistogramMap is allocated upon call to Enable().
|
||||
// The histogram getter functions, which return pointer values to the histograms
|
||||
// in the map, are cached in WebRTC. Therefore, this memory is not freed by the
|
||||
// application (the memory will be reclaimed by the OS).
|
||||
static RtcHistogramMap* volatile g_rtc_histogram_map = nullptr;
|
||||
static std::atomic<RtcHistogramMap*> g_rtc_histogram_map(nullptr);
|
||||
|
||||
void CreateMap() {
|
||||
RtcHistogramMap* map = rtc::AtomicOps::AcquireLoadPtr(&g_rtc_histogram_map);
|
||||
RtcHistogramMap* map = g_rtc_histogram_map.load(std::memory_order_acquire);
|
||||
if (map == nullptr) {
|
||||
RtcHistogramMap* new_map = new RtcHistogramMap();
|
||||
RtcHistogramMap* old_map = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
&g_rtc_histogram_map, static_cast<RtcHistogramMap*>(nullptr), new_map);
|
||||
if (old_map != nullptr)
|
||||
if (!g_rtc_histogram_map.compare_exchange_strong(map, new_map))
|
||||
delete new_map;
|
||||
}
|
||||
}
|
||||
@ -202,15 +204,15 @@ void CreateMap() {
|
||||
// Set the first time we start using histograms. Used to make sure Enable() is
|
||||
// not called thereafter.
|
||||
#if RTC_DCHECK_IS_ON
|
||||
static volatile int g_rtc_histogram_called = 0;
|
||||
static std::atomic<int> g_rtc_histogram_called(0);
|
||||
#endif
|
||||
|
||||
// Gets the map (or nullptr).
|
||||
RtcHistogramMap* GetMap() {
|
||||
#if RTC_DCHECK_IS_ON
|
||||
rtc::AtomicOps::ReleaseStore(&g_rtc_histogram_called, 1);
|
||||
g_rtc_histogram_called.store(1, std::memory_order_release);
|
||||
#endif
|
||||
return g_rtc_histogram_map;
|
||||
return g_rtc_histogram_map.load();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -222,7 +224,7 @@ RtcHistogramMap* GetMap() {
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
Histogram* HistogramFactoryGetCounts(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
@ -235,7 +237,7 @@ Histogram* HistogramFactoryGetCounts(const std::string& name,
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
Histogram* HistogramFactoryGetCountsLinear(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
@ -250,7 +252,7 @@ Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
Histogram* HistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
@ -260,12 +262,12 @@ Histogram* HistogramFactoryGetEnumeration(const std::string& name,
|
||||
}
|
||||
|
||||
// Our default implementation reuses the non-sparse histogram.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary) {
|
||||
return HistogramFactoryGetEnumeration(name, boundary);
|
||||
}
|
||||
|
||||
// Fast path. Adds |sample| to cached |histogram_pointer|.
|
||||
// Fast path. Adds `sample` to cached `histogram_pointer`.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample) {
|
||||
RtcHistogram* ptr = reinterpret_cast<RtcHistogram*>(histogram_pointer);
|
||||
ptr->Add(sample);
|
||||
@ -273,7 +275,7 @@ void HistogramAdd(Histogram* histogram_pointer, int sample) {
|
||||
|
||||
#endif // WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
|
||||
SampleInfo::SampleInfo(const std::string& name,
|
||||
SampleInfo::SampleInfo(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
size_t bucket_count)
|
||||
@ -283,15 +285,16 @@ SampleInfo::~SampleInfo() {}
|
||||
|
||||
// Implementation of global functions in metrics.h.
|
||||
void Enable() {
|
||||
RTC_DCHECK(g_rtc_histogram_map == nullptr);
|
||||
RTC_DCHECK(g_rtc_histogram_map.load() == nullptr);
|
||||
#if RTC_DCHECK_IS_ON
|
||||
RTC_DCHECK_EQ(0, rtc::AtomicOps::AcquireLoad(&g_rtc_histogram_called));
|
||||
RTC_DCHECK_EQ(0, g_rtc_histogram_called.load(std::memory_order_acquire));
|
||||
#endif
|
||||
CreateMap();
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) {
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>, rtc::AbslStringViewCmp>*
|
||||
histograms) {
|
||||
histograms->clear();
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
@ -304,22 +307,22 @@ void Reset() {
|
||||
map->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(const std::string& name, int sample) {
|
||||
int NumEvents(absl::string_view name, int sample) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumEvents(name, sample) : 0;
|
||||
}
|
||||
|
||||
int NumSamples(const std::string& name) {
|
||||
int NumSamples(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumSamples(name) : 0;
|
||||
}
|
||||
|
||||
int MinSample(const std::string& name) {
|
||||
int MinSample(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->MinSample(name) : -1;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(const std::string& name) {
|
||||
std::map<int, int> Samples(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->Samples(name) : std::map<int, int>();
|
||||
}
|
||||
|
Reference in New Issue
Block a user