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:
Arun Raghavan
2023-12-12 10:42:58 -05:00
parent 9a202fb8c2
commit c6abf6cd3f
479 changed files with 20900 additions and 11996 deletions

View File

@ -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" ]

View File

@ -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 {

View 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_

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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

View 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

View File

@ -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

View File

@ -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>();
}