proxygen
TimeUtilTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include <thread>
17 
18 #include <glog/logging.h>
19 
23 
24 using folly::TimePoint;
25 using namespace std::literals::chrono_literals;
26 using std::chrono::duration_cast;
27 using std::chrono::milliseconds;
28 using std::chrono::nanoseconds;
29 using std::chrono::steady_clock;
30 
31 // Define a PrintTo() function for std::chrono::nanoseconds so that these
32 // will be printed nicely on EXPECT*() failures.
33 // Define this in std::chrono so that argument-dependent lookup works.
34 namespace std {
35 namespace chrono {
36 static inline void PrintTo(nanoseconds ns, ::std::ostream* os) {
37  *os << ns.count() << "ns";
38 }
39 } // namespace chrono
40 } // namespace std
41 
42 #ifdef __linux__
43 void runThread(nanoseconds duration, nanoseconds* timeWaiting) {
45 
46  // Loop consuming CPU until the duration has expired.
47  while (true) {
48  TimePoint now;
49  if (now.getTimeStart() - start.getTimeStart() > duration) {
50  // Time to quit
51  // Report how long we spent waiting to be scheduled on the CPU.
52  *timeWaiting = (now.getTimeWaiting() - start.getTimeWaiting());
53  VLOG(1) << "thread " << start.getTid() << ": elapsed "
54  << duration_cast<milliseconds>(
55  now.getTimeStart() - start.getTimeStart())
56  .count()
57  << "ms, time waiting: "
58  << duration_cast<milliseconds>(*timeWaiting).count() << "ms";
59  break;
60  }
61  }
62 }
63 
64 // Test to make sure that TimePoint computes sane values for time
65 // spent waiting on CPU.
66 TEST(TimeUtil, getTimeWaiting) {
67  TimePoint tp;
68 
69  // Run twice as many threads as CPU cores, to ensure that some of
70  // them should be waiting sometime.
71  auto numThreads = sysconf(_SC_NPROCESSORS_CONF) * 2;
72 
73  std::vector<std::thread> threads;
74  std::vector<nanoseconds> timeWaiting;
75  timeWaiting.resize(numThreads, 0ns);
76 
77  auto start = steady_clock::now();
78  for (int n = 0; n < numThreads; ++n) {
79  threads.emplace_back(runThread, 1s, &timeWaiting[n]);
80  }
81 
82  for (auto& thread : threads) {
83  thread.join();
84  }
85  auto end = steady_clock::now();
86 
87  auto timeSpent = end - start;
88  nanoseconds max{0};
89  for (int n = 0; n < numThreads; ++n) {
90  max = std::max(max, timeWaiting[n]);
91  // No thread could possibly have been waiting for longer than
92  // the test actually took to run.
93  EXPECT_LT(timeWaiting[n], timeSpent);
94  }
95  // Make sure that at least one thread spent some time waiting
96  EXPECT_GE(max, 1ns);
97 }
98 #endif
chrono
Definition: CMakeCache.txt:563
#define TEST(test_case_name, test_name)
Definition: gtest.h:2187
std::chrono::nanoseconds getTimeWaiting() const
Definition: TimeUtil.h:62
LogLevel max
Definition: LogLevel.cpp:31
std::chrono::steady_clock::time_point now()
static void PrintTo(nanoseconds ns,::std::ostream *os)
STL namespace.
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
std::vector< std::thread::id > threads
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
pid_t getTid() const
Definition: TimeUtil.h:66
std::chrono::steady_clock::time_point getTimeStart() const
Definition: TimeUtil.h:54
TimeUtilGeneric<> TimeUtil
Definition: Time.h:194
auto start
int * count
static set< string > s
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
StatsClock::time_point TimePoint