proxygen
MemoryIdlerTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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 
18 
22 
23 #include <memory>
24 #include <thread>
25 
26 using namespace folly;
27 using namespace folly::detail;
28 using namespace testing;
29 
30 TEST(MemoryIdler, releaseStack) {
32 }
33 
34 TEST(MemoryIdler, releaseStackMinExtra) {
36 }
37 
38 TEST(MemoryIdler, releaseStackLargeExtra) {
40 }
41 
42 TEST(MemoryIdler, releaseMallocTLS) {
43  auto p = new int[4];
45  delete[] p;
47  p = new int[4];
49  delete[] p;
50 }
51 
56 struct MockClock {
57  using duration = std::chrono::steady_clock::duration;
58  using time_point = std::chrono::time_point<MockClock, duration>;
59 
60  MOCK_METHOD0(nowImpl, time_point());
61 
63  static std::shared_ptr<StrictMock<MockClock>> setup() {
64  auto rv = std::make_shared<StrictMock<MockClock>>();
65  s_mockClockInstance = rv;
66  return rv;
67  }
68 
69  static time_point now() {
70  return s_mockClockInstance.lock()->nowImpl();
71  }
72 
73  static std::weak_ptr<StrictMock<MockClock>> s_mockClockInstance;
74 };
75 
76 std::weak_ptr<StrictMock<MockClock>> MockClock::s_mockClockInstance;
77 static auto const forever = MockClock::time_point::max();
78 
86 template <typename T>
87 struct MockAtom : public std::atomic<T> {
88  explicit MockAtom(T init = 0) : std::atomic<T>(init) {}
89 
94 };
95 
97 futexWait(const Futex<MockAtom>* futex, uint32_t expected, uint32_t waitMask) {
98  return futex->futexWait(expected, waitMask);
99 }
100 template <typename Clock, typename Duration>
102  const Futex<MockAtom>* futex,
103  std::uint32_t expected,
104  std::chrono::time_point<Clock, Duration> const& deadline,
105  uint32_t waitMask) {
106  return futex->futexWaitUntil(expected, deadline, waitMask);
107 }
108 
109 TEST(MemoryIdler, futexWaitValueChangedEarly) {
110  Futex<MockAtom> fut;
111  auto clock = MockClock::setup();
112  auto begin = MockClock::time_point(std::chrono::seconds(100));
113  auto idleTimeout = MemoryIdler::defaultIdleTimeout.load();
114 
115  EXPECT_CALL(*clock, nowImpl()).WillOnce(Return(begin));
116  EXPECT_CALL(
117  fut,
119  1, AllOf(Ge(begin + idleTimeout), Lt(begin + 2 * idleTimeout)), -1))
121  EXPECT_EQ(
123 }
124 
125 TEST(MemoryIdler, futexWaitValueChangedLate) {
126  Futex<MockAtom> fut;
127  auto clock = MockClock::setup();
128  auto begin = MockClock::time_point(std::chrono::seconds(100));
129  auto idleTimeout = MemoryIdler::defaultIdleTimeout.load();
130 
131  EXPECT_CALL(*clock, nowImpl()).WillOnce(Return(begin));
132  EXPECT_CALL(
133  fut,
135  1, AllOf(Ge(begin + idleTimeout), Lt(begin + 2 * idleTimeout)), -1))
136  .WillOnce(Return(FutexResult::TIMEDOUT));
137  EXPECT_CALL(fut, futexWaitUntil(1, forever, -1))
139  EXPECT_EQ(
141 }
142 
143 TEST(MemoryIdler, futexWaitAwokenEarly) {
144  Futex<MockAtom> fut;
145  auto clock = MockClock::setup();
146  auto begin = MockClock::time_point(std::chrono::seconds(100));
147  auto idleTimeout = MemoryIdler::defaultIdleTimeout.load();
148 
149  EXPECT_CALL(*clock, nowImpl()).WillOnce(Return(begin));
150  EXPECT_CALL(fut, futexWaitUntil(1, Ge(begin + idleTimeout), -1))
151  .WillOnce(Return(FutexResult::AWOKEN));
153 }
154 
155 TEST(MemoryIdler, futexWaitAwokenLate) {
156  Futex<MockAtom> fut;
157  auto clock = MockClock::setup();
158  auto begin = MockClock::time_point(std::chrono::seconds(100));
159  auto idleTimeout = MemoryIdler::defaultIdleTimeout.load();
160 
161  EXPECT_CALL(*clock, nowImpl()).WillOnce(Return(begin));
162  EXPECT_CALL(fut, futexWaitUntil(1, begin + idleTimeout, -1))
163  .WillOnce(Return(FutexResult::TIMEDOUT));
164  EXPECT_CALL(fut, futexWaitUntil(1, forever, -1))
165  .WillOnce(Return(FutexResult::AWOKEN));
166  EXPECT_EQ(
168  MemoryIdler::futexWaitUntil(fut, 1, forever, -1, idleTimeout, 100, 0.0f));
169 }
170 
171 TEST(MemoryIdler, futexWaitImmediateFlush) {
172  Futex<MockAtom> fut;
173  auto clock = MockClock::setup();
174 
175  EXPECT_CALL(fut, futexWaitUntil(2, forever, 0xff))
176  .WillOnce(Return(FutexResult::AWOKEN));
177  EXPECT_EQ(
180  fut, 2, forever, 0xff, std::chrono::seconds(0)));
181 }
182 
183 TEST(MemoryIdler, futexWaitNeverFlush) {
184  Futex<MockAtom> fut;
185  auto clock = MockClock::setup();
186 
187  EXPECT_CALL(fut, futexWaitUntil(1, forever, -1))
188  .WillOnce(Return(FutexResult::AWOKEN));
189  EXPECT_EQ(
192  fut, 1, forever, -1, std::chrono::seconds(-7)));
193 }
static FutexResult futexWaitUntil(Futex &fut, uint32_t expected, Deadline const &deadline, uint32_t waitMask=-1, IdleTime const &idleTimeout=defaultIdleTimeout.load(std::memory_order_acquire), size_t stackToRetain=kDefaultStackToRetain, float timeoutVariationFrac=0.5)
Definition: MemoryIdler.h:139
auto f
static void unmapUnusedStack(size_t retain=kDefaultStackToRetain)
LogLevel max
Definition: LogLevel.cpp:31
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static std::weak_ptr< StrictMock< MockClock > > s_mockClockInstance
static time_point now()
static auto const forever
Atom< std::uint32_t > Futex
Definition: Futex.h:51
STL namespace.
auto begin(TestAdlIterable &instance)
Definition: ForeachTest.cpp:56
folly::std T
T load(std::memory_order mo=std::memory_order_seq_cst) const noexcept
Definition: AtomicStruct.h:141
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
FutexResult futexWait(const Futex *futex, uint32_t expected, uint32_t waitMask)
Definition: Futex-inl.h:100
MockAtom(T init=0)
internal::LtMatcher< Rhs > Lt(Rhs x)
void init(int *argc, char ***argv, bool removeFlags)
Definition: Init.cpp:34
FutexResult futexWaitUntil(const Futex *futex, uint32_t expected, std::chrono::time_point< Clock, Duration > const &deadline, uint32_t waitMask)
Definition: Futex-inl.h:112
#define MOCK_CONST_METHOD3(m,...)
static std::shared_ptr< StrictMock< MockClock > > setup()
Hold on to the returned shared_ptr until the end of the test.
StrictConjunction< T< As >... > AllOf
std::chrono::steady_clock::duration duration
static AtomicStruct< std::chrono::steady_clock::duration > defaultIdleTimeout
Definition: MemoryIdler.h:64
#define MOCK_CONST_METHOD2(m,...)
#define EXPECT_CALL(obj, call)
internal::GeMatcher< Rhs > Ge(Rhs x)
std::chrono::steady_clock::time_point time_point
TEST(SequencedExecutor, CPUThreadPoolExecutor)
static void flushLocalMallocCaches()
Definition: MemoryIdler.cpp:41
internal::ReturnAction< R > Return(R value)
#define MOCK_METHOD0(m,...)