fixup! [M120 Migration] Notify media device state to webbrowser
[platform/framework/web/chromium-efl.git] / base / observer_list_perftest.cc
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/observer_list.h"
6
7 #include <memory>
8
9 #include "base/check_op.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/perf/perf_result_reporter.h"
14
15 // Ask the compiler not to use a register for this counter, in case it decides
16 // to do magic optimizations like |counter += kLaps|.
17 volatile int g_observer_list_perf_test_counter;
18
19 namespace base {
20
21 constexpr char kMetricPrefixObserverList[] = "ObserverList.";
22 constexpr char kMetricNotifyTimePerObserver[] = "notify_time_per_observer";
23
24 namespace {
25
26 perf_test::PerfResultReporter SetUpReporter(const std::string& story_name) {
27   perf_test::PerfResultReporter reporter(kMetricPrefixObserverList, story_name);
28   reporter.RegisterImportantMetric(kMetricNotifyTimePerObserver, "ns");
29   return reporter;
30 }
31
32 }  // namespace
33
34 class ObserverInterface {
35  public:
36   ObserverInterface() = default;
37   ObserverInterface(const ObserverInterface&) = delete;
38   ObserverInterface& operator=(const ObserverInterface&) = delete;
39   virtual ~ObserverInterface() = default;
40   virtual void Observe() const {
41     g_observer_list_perf_test_counter = g_observer_list_perf_test_counter + 1;
42   }
43 };
44
45 class UnsafeObserver : public ObserverInterface {};
46
47 class TestCheckedObserver : public CheckedObserver, public ObserverInterface {};
48
49 template <class ObserverType>
50 struct Pick {
51   // The ObserverList type to use. Checked observers need to be in a checked
52   // ObserverList.
53   using ObserverListType = ObserverList<ObserverType>;
54   static const char* GetName() { return "CheckedObserver"; }
55 };
56 template <>
57 struct Pick<UnsafeObserver> {
58   using ObserverListType = ObserverList<ObserverInterface>::Unchecked;
59   static const char* GetName() { return "UnsafeObserver"; }
60 };
61
62 template <class ObserverType>
63 class ObserverListPerfTest : public ::testing::Test {
64  public:
65   using ObserverListType = typename Pick<ObserverType>::ObserverListType;
66
67   ObserverListPerfTest() = default;
68   ObserverListPerfTest(const ObserverListPerfTest&) = delete;
69   ObserverListPerfTest& operator=(const ObserverListPerfTest&) = delete;
70 };
71
72 typedef ::testing::Types<UnsafeObserver, TestCheckedObserver> ObserverTypes;
73 TYPED_TEST_SUITE(ObserverListPerfTest, ObserverTypes);
74
75 // Performance test for base::ObserverList and Checked Observers.
76 TYPED_TEST(ObserverListPerfTest, NotifyPerformance) {
77   constexpr int kMaxObservers = 128;
78 #if DCHECK_IS_ON()
79   // The test takes about 100x longer in debug builds, mostly due to sequence
80   // checker overheads when WeakPtr gets involved.
81   constexpr int kLaps = 1000000;
82 #else
83   constexpr int kLaps = 100000000;
84 #endif
85   constexpr int kWarmupLaps = 100;
86   std::vector<std::unique_ptr<TypeParam>> observers;
87
88   for (int observer_count = 0; observer_count <= kMaxObservers;
89        observer_count = observer_count ? observer_count * 2 : 1) {
90     typename TestFixture::ObserverListType list;
91     for (int i = 0; i < observer_count; ++i)
92       observers.push_back(std::make_unique<TypeParam>());
93     for (auto& o : observers)
94       list.AddObserver(o.get());
95
96     for (int i = 0; i < kWarmupLaps; ++i) {
97       for (auto& o : list)
98         o.Observe();
99     }
100     g_observer_list_perf_test_counter = 0;
101     const int weighted_laps = kLaps / (observer_count + 1);
102
103     TimeTicks start = TimeTicks::Now();
104     for (int i = 0; i < weighted_laps; ++i) {
105       for (auto& o : list)
106         o.Observe();
107     }
108     TimeDelta duration = TimeTicks::Now() - start;
109
110     observers.clear();
111
112     EXPECT_EQ(observer_count * weighted_laps,
113               g_observer_list_perf_test_counter);
114     EXPECT_TRUE(observer_count == 0 || !list.empty());
115
116     std::string story_name =
117         base::StringPrintf("%s_%d", Pick<TypeParam>::GetName(), observer_count);
118
119     // A typical value is 3-20 nanoseconds per observe in Release, 1000-2000ns
120     // in an optimized build with DCHECKs and 3000-6000ns in debug builds.
121     auto reporter = SetUpReporter(story_name);
122     reporter.AddResult(
123         kMetricNotifyTimePerObserver,
124         duration.InNanoseconds() /
125             static_cast<double>(g_observer_list_perf_test_counter +
126                                 weighted_laps));
127   }
128 }
129
130 }  // namespace base