xref: /aosp_15_r20/external/cronet/base/synchronization/lock_perftest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
6*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
7*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/timer/lap_timer.h"
11*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
12*6777b538SAndroid Build Coastguard Worker #include "testing/perf/perf_result_reporter.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace base {
15*6777b538SAndroid Build Coastguard Worker namespace {
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker constexpr int kWarmupRuns = 1;
18*6777b538SAndroid Build Coastguard Worker constexpr TimeDelta kTimeLimit = Seconds(1);
19*6777b538SAndroid Build Coastguard Worker constexpr int kTimeCheckInterval = 100000;
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker constexpr char kMetricPrefixLock[] = "Lock.";
22*6777b538SAndroid Build Coastguard Worker constexpr char kMetricLockUnlockThroughput[] = "lock_unlock_throughput";
23*6777b538SAndroid Build Coastguard Worker constexpr char kStoryBaseline[] = "baseline_story";
24*6777b538SAndroid Build Coastguard Worker constexpr char kStoryWithCompetingThread[] = "with_competing_thread";
25*6777b538SAndroid Build Coastguard Worker 
SetUpReporter(const std::string & story_name)26*6777b538SAndroid Build Coastguard Worker perf_test::PerfResultReporter SetUpReporter(const std::string& story_name) {
27*6777b538SAndroid Build Coastguard Worker   perf_test::PerfResultReporter reporter(kMetricPrefixLock, story_name);
28*6777b538SAndroid Build Coastguard Worker   reporter.RegisterImportantMetric(kMetricLockUnlockThroughput, "runs/s");
29*6777b538SAndroid Build Coastguard Worker   return reporter;
30*6777b538SAndroid Build Coastguard Worker }
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker class Spin : public PlatformThread::Delegate {
33*6777b538SAndroid Build Coastguard Worker  public:
Spin(Lock * lock,uint32_t * data)34*6777b538SAndroid Build Coastguard Worker   Spin(Lock* lock, uint32_t* data)
35*6777b538SAndroid Build Coastguard Worker       : lock_(lock), data_(data), should_stop_(false) {}
36*6777b538SAndroid Build Coastguard Worker   ~Spin() override = default;
37*6777b538SAndroid Build Coastguard Worker 
ThreadMain()38*6777b538SAndroid Build Coastguard Worker   void ThreadMain() override {
39*6777b538SAndroid Build Coastguard Worker     // Local variable to avoid "cache line ping-pong" from influencing the
40*6777b538SAndroid Build Coastguard Worker     // results.
41*6777b538SAndroid Build Coastguard Worker     uint32_t count = 0;
42*6777b538SAndroid Build Coastguard Worker     while (!should_stop_.load(std::memory_order_relaxed)) {
43*6777b538SAndroid Build Coastguard Worker       lock_->Acquire();
44*6777b538SAndroid Build Coastguard Worker       count++;
45*6777b538SAndroid Build Coastguard Worker       lock_->Release();
46*6777b538SAndroid Build Coastguard Worker     }
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker     lock_->Acquire();
49*6777b538SAndroid Build Coastguard Worker     (*data_) += count;
50*6777b538SAndroid Build Coastguard Worker     lock_->Release();
51*6777b538SAndroid Build Coastguard Worker   }
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   // Called from another thread to stop the loop.
Stop()54*6777b538SAndroid Build Coastguard Worker   void Stop() { should_stop_ = true; }
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker  private:
57*6777b538SAndroid Build Coastguard Worker   raw_ptr<Lock> lock_;
58*6777b538SAndroid Build Coastguard Worker   raw_ptr<uint32_t> data_ GUARDED_BY(lock_);
59*6777b538SAndroid Build Coastguard Worker   std::atomic<bool> should_stop_;
60*6777b538SAndroid Build Coastguard Worker };
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker }  // namespace
63*6777b538SAndroid Build Coastguard Worker 
TEST(LockPerfTest,Simple)64*6777b538SAndroid Build Coastguard Worker TEST(LockPerfTest, Simple) {
65*6777b538SAndroid Build Coastguard Worker   LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval);
66*6777b538SAndroid Build Coastguard Worker   [[maybe_unused]] uint32_t data = 0;
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   Lock lock;
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   do {
71*6777b538SAndroid Build Coastguard Worker     lock.Acquire();
72*6777b538SAndroid Build Coastguard Worker     data += 1;
73*6777b538SAndroid Build Coastguard Worker     lock.Release();
74*6777b538SAndroid Build Coastguard Worker     timer.NextLap();
75*6777b538SAndroid Build Coastguard Worker   } while (!timer.HasTimeLimitExpired());
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   auto reporter = SetUpReporter(kStoryBaseline);
78*6777b538SAndroid Build Coastguard Worker   reporter.AddResult(kMetricLockUnlockThroughput, timer.LapsPerSecond());
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker 
TEST(LockPerfTest,WithCompetingThread)81*6777b538SAndroid Build Coastguard Worker TEST(LockPerfTest, WithCompetingThread) {
82*6777b538SAndroid Build Coastguard Worker   LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval);
83*6777b538SAndroid Build Coastguard Worker   uint32_t data = 0;
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker   Lock lock;
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker   // Starts a competing thread executing the same loop as this thread.
88*6777b538SAndroid Build Coastguard Worker   Spin thread_main(&lock, &data);
89*6777b538SAndroid Build Coastguard Worker   PlatformThreadHandle thread_handle;
90*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(PlatformThread::Create(0, &thread_main, &thread_handle));
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker   do {
93*6777b538SAndroid Build Coastguard Worker     lock.Acquire();
94*6777b538SAndroid Build Coastguard Worker     data += 1;
95*6777b538SAndroid Build Coastguard Worker     lock.Release();
96*6777b538SAndroid Build Coastguard Worker     timer.NextLap();
97*6777b538SAndroid Build Coastguard Worker   } while (!timer.HasTimeLimitExpired());
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   thread_main.Stop();
100*6777b538SAndroid Build Coastguard Worker   PlatformThread::Join(thread_handle);
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker   auto reporter = SetUpReporter(kStoryWithCompetingThread);
103*6777b538SAndroid Build Coastguard Worker   reporter.AddResult(kMetricLockUnlockThroughput, timer.LapsPerSecond());
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker }  // namespace base
106