Try to fix IdleTime unit test
authorHaijun Zhu <haijunz@fb.com>
Tue, 20 Jan 2015 18:54:59 +0000 (10:54 -0800)
committerwoo <woo@fb.com>
Mon, 2 Feb 2015 21:11:48 +0000 (13:11 -0800)
Summary:
IdleTime unit test has been failing randomly (#5996886). The
event base loop calculates an exponentially moving average of loop busy
time in each loop. In the test, the busy time is initialized to 5900 and
each loop runs more than 8000 us. In normal case decaying of the
previous loop busy time will take 6 loops to  move this average to >6000.
But if the test is running on a heavily loaded machine the busy+idle time
a loop is longer than it should be, causing the decaying happen faster.
This diff skips this test if this happens.

Test Plan:
It won't affect anything if running on my devserver. It only
helps on a heavily loaded contbuild host.

Reviewed By: alandau@fb.com

Subscribers: folly-diffs@

FB internal diff: D1788450

Tasks: 5996886

Signature: t1:1788450:1421460774:1ec575c50f881e10b5a0208717fe68164f0d0f57

folly/io/async/EventBase.cpp
folly/io/async/test/EventBaseTest.cpp

index 7bfc221368921f49b0e3cae3eeae7842ec635c69..e956ca1881623e245369394c6e297243072956ae 100644 (file)
@@ -646,6 +646,8 @@ void EventBase::SmoothLoopTime::addSample(int64_t idle, int64_t busy) {
       LEFT = 2,   // busy sample placed at the beginning of the iteration
     };
 
+  // See http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
+  // and D676020 for more info on this calculation.
   VLOG(11) << "idle " << idle << " oldBusyLeftover_ " << oldBusyLeftover_ <<
               " idle + oldBusyLeftover_ " << idle + oldBusyLeftover_ <<
               " busy " << busy << " " << __PRETTY_FUNCTION__;
index c98871699e7ba1aafce7c9f2d35ff0325ca58d9b..cacf18feb8a40bbacf7504d001ba9d5e907fc622 100644 (file)
@@ -34,6 +34,8 @@ using std::make_pair;
 using std::cerr;
 using std::endl;
 using std::chrono::milliseconds;
+using std::chrono::microseconds;
+using std::chrono::duration_cast;
 
 using namespace folly;
 
@@ -1456,6 +1458,9 @@ TEST(EventBaseTest, IdleTime) {
   IdleTimeTimeoutSeries tos0(&eventBase, timeouts0);
   std::deque<uint64_t> timeouts(20, 20);
   std::unique_ptr<IdleTimeTimeoutSeries> tos;
+  int64_t testStart = duration_cast<microseconds>(
+    std::chrono::steady_clock::now().time_since_epoch()).count();
+  bool hostOverloaded = false;
 
   int latencyCallbacks = 0;
   eventBase.setMaxLatency(6000, [&]() {
@@ -1463,6 +1468,15 @@ TEST(EventBaseTest, IdleTime) {
 
     switch (latencyCallbacks) {
     case 1:
+      if (tos0.getTimeouts() < 6) {
+        // This could only happen if the host this test is running
+        // on is heavily loaded.
+        int64_t maxLatencyReached = duration_cast<microseconds>(
+            std::chrono::steady_clock::now().time_since_epoch()).count();
+        ASSERT_LE(43800, maxLatencyReached - testStart);
+        hostOverloaded = true;
+        break;
+      }
       ASSERT_EQ(6, tos0.getTimeouts());
       ASSERT_GE(6100, eventBase.getAvgLoopTime() - 1200);
       ASSERT_LE(6100, eventBase.getAvgLoopTime() + 1200);
@@ -1480,6 +1494,10 @@ TEST(EventBaseTest, IdleTime) {
 
   eventBase.loop();
 
+  if (hostOverloaded) {
+    return;
+  }
+
   ASSERT_EQ(1, latencyCallbacks);
   ASSERT_EQ(7, tos0.getTimeouts());
   ASSERT_GE(5900, eventBase.getAvgLoopTime() - 1200);