Re-sync with internal repository
[hiphop-php.git] / third-party / folly / src / folly / io / async / test / TimeUtilTest.cpp
blob1deae32c512aa74a2bfa41361a44d14a34491c8b
1 /*
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>
19 #include <thread>
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.
36 namespace std {
37 namespace chrono {
38 static inline void PrintTo(nanoseconds ns, ::std::ostream* os) {
39 *os << ns.count() << "ns";
41 } // namespace chrono
42 } // namespace std
44 #ifdef __linux__
45 void runThread(nanoseconds duration, nanoseconds* timeWaiting) {
46 TimePoint start;
48 // Loop consuming CPU until the duration has expired.
49 while (true) {
50 TimePoint now;
51 if (now.getTimeStart() - start.getTimeStart() > duration) {
52 // Time to quit
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())
58 .count()
59 << "ms, time waiting: "
60 << duration_cast<milliseconds>(*timeWaiting).count() << "ms";
61 break;
66 // Test to make sure that TimePoint computes sane values for time
67 // spent waiting on CPU.
68 TEST(TimeUtil, getTimeWaiting) {
69 TimePoint tp;
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) {
85 thread.join();
87 auto end = steady_clock::now();
89 auto timeSpent = end - start;
90 nanoseconds max{0};
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
98 EXPECT_GE(max, 1ns);
100 #endif