2 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/io/async/test/TimeUtil.h>
21 #include <glog/logging.h>
23 #include <folly/portability/GTest.h>
24 #include <folly/portability/Unistd.h>
26 using folly::TimePoint
;
27 using namespace std::literals::chrono_literals
;
28 using std::chrono::duration_cast
;
29 using std::chrono::milliseconds
;
30 using std::chrono::nanoseconds
;
31 using std::chrono::steady_clock
;
33 // Define a PrintTo() function for std::chrono::nanoseconds so that these
34 // will be printed nicely on EXPECT*() failures.
35 // Define this in std::chrono so that argument-dependent lookup works.
38 static inline void PrintTo(nanoseconds ns
, ::std::ostream
* os
) {
39 *os
<< ns
.count() << "ns";
45 void runThread(nanoseconds duration
, nanoseconds
* timeWaiting
) {
48 // Loop consuming CPU until the duration has expired.
51 if (now
.getTimeStart() - start
.getTimeStart() > duration
) {
53 // Report how long we spent waiting to be scheduled on the CPU.
54 *timeWaiting
= (now
.getTimeWaiting() - start
.getTimeWaiting());
55 VLOG(1) << "thread " << start
.getTid() << ": elapsed "
56 << duration_cast
<milliseconds
>(
57 now
.getTimeStart() - start
.getTimeStart())
59 << "ms, time waiting: "
60 << duration_cast
<milliseconds
>(*timeWaiting
).count() << "ms";
66 // Test to make sure that TimePoint computes sane values for time
67 // spent waiting on CPU.
68 TEST(TimeUtil
, getTimeWaiting
) {
71 // Run twice as many threads as CPU cores, to ensure that some of
72 // them should be waiting sometime.
73 auto numThreads
= sysconf(_SC_NPROCESSORS_CONF
) * 2;
75 std::vector
<std::thread
> threads
;
76 std::vector
<nanoseconds
> timeWaiting
;
77 timeWaiting
.resize(numThreads
, 0ns
);
79 auto start
= steady_clock::now();
80 for (int n
= 0; n
< numThreads
; ++n
) {
81 threads
.emplace_back(runThread
, 1s
, &timeWaiting
[n
]);
84 for (auto& thread
: threads
) {
87 auto end
= steady_clock::now();
89 auto timeSpent
= end
- start
;
91 for (int n
= 0; n
< numThreads
; ++n
) {
92 max
= std::max(max
, timeWaiting
[n
]);
93 // No thread could possibly have been waiting for longer than
94 // the test actually took to run.
95 EXPECT_LT(timeWaiting
[n
], timeSpent
);
97 // Make sure that at least one thread spent some time waiting