1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/cpu_time.h"
12
13 #include "rtc_base/platform_thread.h"
14 #include "rtc_base/time_utils.h"
15 #include "system_wrappers/include/sleep.h"
16 #include "test/gtest.h"
17
18 // Only run these tests on non-instrumented builds, because timing on
19 // instrumented builds is unreliable, causing the test to be flaky.
20 #if defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \
21 defined(ADDRESS_SANITIZER)
22 #define MAYBE_TEST(test_name) DISABLED_##test_name
23 #else
24 #define MAYBE_TEST(test_name) test_name
25 #endif
26
27 namespace {
28 const int kAllowedErrorMillisecs = 30;
29 const int kProcessingTimeMillisecs = 500;
30 const int kWorkingThreads = 2;
31
32 // Consumes approximately kProcessingTimeMillisecs of CPU time in single thread.
WorkingFunction(void * counter_pointer)33 void WorkingFunction(void* counter_pointer) {
34 int64_t* counter = reinterpret_cast<int64_t*>(counter_pointer);
35 *counter = 0;
36 int64_t stop_cpu_time =
37 rtc::GetThreadCpuTimeNanos() +
38 kProcessingTimeMillisecs * rtc::kNumNanosecsPerMillisec;
39 while (rtc::GetThreadCpuTimeNanos() < stop_cpu_time) {
40 (*counter)++;
41 }
42 }
43 } // namespace
44
45 namespace rtc {
46
47 // A minimal test which can be run on instrumented builds, so that they're at
48 // least exercising the code to check for memory leaks/etc.
TEST(CpuTimeTest,BasicTest)49 TEST(CpuTimeTest, BasicTest) {
50 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
51 int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
52 int64_t process_duration_nanos =
53 GetProcessCpuTimeNanos() - process_start_time_nanos;
54 int64_t thread_duration_nanos =
55 GetThreadCpuTimeNanos() - thread_start_time_nanos;
56 EXPECT_GE(process_duration_nanos, 0);
57 EXPECT_GE(thread_duration_nanos, 0);
58 }
59
TEST(CpuTimeTest,MAYBE_TEST (TwoThreads))60 TEST(CpuTimeTest, MAYBE_TEST(TwoThreads)) {
61 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
62 int64_t thread_start_time_nanos = GetThreadCpuTimeNanos();
63 int64_t counter1;
64 int64_t counter2;
65 PlatformThread thread1(WorkingFunction, reinterpret_cast<void*>(&counter1),
66 "Thread1");
67 PlatformThread thread2(WorkingFunction, reinterpret_cast<void*>(&counter2),
68 "Thread2");
69 thread1.Start();
70 thread2.Start();
71 thread1.Stop();
72 thread2.Stop();
73
74 EXPECT_GE(counter1, 0);
75 EXPECT_GE(counter2, 0);
76 int64_t process_duration_nanos =
77 GetProcessCpuTimeNanos() - process_start_time_nanos;
78 int64_t thread_duration_nanos =
79 GetThreadCpuTimeNanos() - thread_start_time_nanos;
80 // This thread did almost nothing. Definetly less work than kProcessingTime.
81 // Therefore GetThreadCpuTime is not a wall clock.
82 EXPECT_LE(thread_duration_nanos,
83 (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
84 kNumNanosecsPerMillisec);
85 // Total process time is at least twice working threads' CPU time.
86 // Therefore process and thread times are correctly related.
87 EXPECT_GE(process_duration_nanos,
88 kWorkingThreads *
89 (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
90 kNumNanosecsPerMillisec);
91 }
92
TEST(CpuTimeTest,MAYBE_TEST (Sleeping))93 TEST(CpuTimeTest, MAYBE_TEST(Sleeping)) {
94 int64_t process_start_time_nanos = GetProcessCpuTimeNanos();
95 webrtc::SleepMs(kProcessingTimeMillisecs);
96 int64_t process_duration_nanos =
97 GetProcessCpuTimeNanos() - process_start_time_nanos;
98 // Sleeping should not introduce any additional CPU time.
99 // Therefore GetProcessCpuTime is not a wall clock.
100 EXPECT_LE(process_duration_nanos,
101 (kProcessingTimeMillisecs - kAllowedErrorMillisecs) *
102 kNumNanosecsPerMillisec);
103 }
104
105 } // namespace rtc
106