Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(662)

Side by Side Diff: webrtc/base/cpumonitor_unittest.cc

Issue 1476453002: Clean up PlatformThread. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: IsRunning DCHECK Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/base/platform_thread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2010 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <iomanip>
12 #include <iostream>
13 #include <vector>
14
15 #if defined(WEBRTC_WIN)
16 #include "webrtc/base/win32.h"
17 #endif
18
19 #include "webrtc/base/cpumonitor.h"
20 #include "webrtc/base/flags.h"
21 #include "webrtc/base/gunit.h"
22 #include "webrtc/base/scoped_ptr.h"
23 #include "webrtc/base/thread.h"
24 #include "webrtc/base/timeutils.h"
25 #include "webrtc/base/timing.h"
26 #include "webrtc/test/testsupport/gtest_disable.h"
27
28 namespace rtc {
29
30 static const int kMaxCpus = 1024;
31 static const int kSettleTime = 100; // Amount of time to between tests.
32 static const int kIdleTime = 500; // Amount of time to be idle in ms.
33 static const int kBusyTime = 1000; // Amount of time to be busy in ms.
34 static const int kLongInterval = 2000; // Interval longer than busy times
35
36 class BusyThread : public rtc::Thread {
37 public:
38 BusyThread(double load, double duration, double interval) :
39 load_(load), duration_(duration), interval_(interval) {
40 }
41 virtual ~BusyThread() {
42 Stop();
43 }
44 void Run() {
45 Timing time;
46 double busy_time = interval_ * load_ / 100.0;
47 for (;;) {
48 time.BusyWait(busy_time);
49 time.IdleWait(interval_ - busy_time);
50 if (duration_) {
51 duration_ -= interval_;
52 if (duration_ <= 0) {
53 break;
54 }
55 }
56 }
57 }
58 private:
59 double load_;
60 double duration_;
61 double interval_;
62 };
63
64 class CpuLoadListener : public sigslot::has_slots<> {
65 public:
66 CpuLoadListener()
67 : current_cpus_(0),
68 cpus_(0),
69 process_load_(.0f),
70 system_load_(.0f),
71 count_(0) {
72 }
73
74 void OnCpuLoad(int current_cpus, int cpus, float proc_load, float sys_load) {
75 current_cpus_ = current_cpus;
76 cpus_ = cpus;
77 process_load_ = proc_load;
78 system_load_ = sys_load;
79 ++count_;
80 }
81
82 int current_cpus() const { return current_cpus_; }
83 int cpus() const { return cpus_; }
84 float process_load() const { return process_load_; }
85 float system_load() const { return system_load_; }
86 int count() const { return count_; }
87
88 private:
89 int current_cpus_;
90 int cpus_;
91 float process_load_;
92 float system_load_;
93 int count_;
94 };
95
96 // Set affinity (which cpu to run on), but respecting FLAG_affinity:
97 // -1 means no affinity - run on whatever cpu is available.
98 // 0 .. N means run on specific cpu. The tool will create N threads and call
99 // SetThreadAffinity on 0 to N - 1 as cpu. FLAG_affinity sets the first cpu
100 // so the range becomes affinity to affinity + N - 1
101 // Note that this function affects Windows scheduling, effectively giving
102 // the thread with affinity for a specified CPU more priority on that CPU.
103 bool SetThreadAffinity(BusyThread* t, int cpu, int affinity) {
104 #if defined(WEBRTC_WIN)
105 if (affinity >= 0) {
106 return ::SetThreadAffinityMask(t->GetHandle(),
107 1 << (cpu + affinity)) != FALSE;
108 }
109 #endif
110 return true;
111 }
112
113 bool SetThreadPriority(BusyThread* t, int prio) {
114 if (!prio) {
115 return true;
116 }
117 bool ok = t->SetPriority(static_cast<rtc::ThreadPriority>(prio));
118 if (!ok) {
119 std::cout << "Error setting thread priority." << std::endl;
120 }
121 return ok;
122 }
123
124 int CpuLoad(double cpuload, double duration, int numthreads,
125 int priority, double interval, int affinity) {
126 int ret = 0;
127 std::vector<BusyThread*> threads;
128 for (int i = 0; i < numthreads; ++i) {
129 threads.push_back(new BusyThread(cpuload, duration, interval));
130 // NOTE(fbarchard): Priority must be done before Start.
131 if (!SetThreadPriority(threads[i], priority) ||
132 !threads[i]->Start() ||
133 !SetThreadAffinity(threads[i], i, affinity)) {
134 ret = 1;
135 break;
136 }
137 }
138 // Wait on each thread
139 if (ret == 0) {
140 for (int i = 0; i < numthreads; ++i) {
141 threads[i]->Stop();
142 }
143 }
144
145 for (int i = 0; i < numthreads; ++i) {
146 delete threads[i];
147 }
148 return ret;
149 }
150
151 // Make 2 CPUs busy
152 static void CpuTwoBusyLoop(int busytime) {
153 CpuLoad(100.0, busytime / 1000.0, 2, 1, 0.050, -1);
154 }
155
156 // Make 1 CPUs busy
157 static void CpuBusyLoop(int busytime) {
158 CpuLoad(100.0, busytime / 1000.0, 1, 1, 0.050, -1);
159 }
160
161 // Make 1 use half CPU time.
162 static void CpuHalfBusyLoop(int busytime) {
163 CpuLoad(50.0, busytime / 1000.0, 1, 1, 0.050, -1);
164 }
165
166 void TestCpuSampler(bool test_proc, bool test_sys, bool force_fallback) {
167 CpuSampler sampler;
168 sampler.set_force_fallback(force_fallback);
169 EXPECT_TRUE(sampler.Init());
170 sampler.set_load_interval(100);
171 int cpus = sampler.GetMaxCpus();
172
173 // Test1: CpuSampler under idle situation.
174 Thread::SleepMs(kSettleTime);
175 sampler.GetProcessLoad();
176 sampler.GetSystemLoad();
177
178 Thread::SleepMs(kIdleTime);
179
180 float proc_idle = 0.f, sys_idle = 0.f;
181 if (test_proc) {
182 proc_idle = sampler.GetProcessLoad();
183 }
184 if (test_sys) {
185 sys_idle = sampler.GetSystemLoad();
186 }
187 if (test_proc) {
188 LOG(LS_INFO) << "ProcessLoad Idle: "
189 << std::setiosflags(std::ios_base::fixed)
190 << std::setprecision(2) << std::setw(6) << proc_idle;
191 EXPECT_GE(proc_idle, 0.f);
192 EXPECT_LE(proc_idle, static_cast<float>(cpus));
193 }
194 if (test_sys) {
195 LOG(LS_INFO) << "SystemLoad Idle: "
196 << std::setiosflags(std::ios_base::fixed)
197 << std::setprecision(2) << std::setw(6) << sys_idle;
198 EXPECT_GE(sys_idle, 0.f);
199 EXPECT_LE(sys_idle, static_cast<float>(cpus));
200 }
201
202 // Test2: CpuSampler with main process at 50% busy.
203 Thread::SleepMs(kSettleTime);
204 sampler.GetProcessLoad();
205 sampler.GetSystemLoad();
206
207 CpuHalfBusyLoop(kBusyTime);
208
209 float proc_halfbusy = 0.f, sys_halfbusy = 0.f;
210 if (test_proc) {
211 proc_halfbusy = sampler.GetProcessLoad();
212 }
213 if (test_sys) {
214 sys_halfbusy = sampler.GetSystemLoad();
215 }
216 if (test_proc) {
217 LOG(LS_INFO) << "ProcessLoad Halfbusy: "
218 << std::setiosflags(std::ios_base::fixed)
219 << std::setprecision(2) << std::setw(6) << proc_halfbusy;
220 EXPECT_GE(proc_halfbusy, 0.f);
221 EXPECT_LE(proc_halfbusy, static_cast<float>(cpus));
222 }
223 if (test_sys) {
224 LOG(LS_INFO) << "SystemLoad Halfbusy: "
225 << std::setiosflags(std::ios_base::fixed)
226 << std::setprecision(2) << std::setw(6) << sys_halfbusy;
227 EXPECT_GE(sys_halfbusy, 0.f);
228 EXPECT_LE(sys_halfbusy, static_cast<float>(cpus));
229 }
230
231 // Test3: CpuSampler with main process busy.
232 Thread::SleepMs(kSettleTime);
233 sampler.GetProcessLoad();
234 sampler.GetSystemLoad();
235
236 CpuBusyLoop(kBusyTime);
237
238 float proc_busy = 0.f, sys_busy = 0.f;
239 if (test_proc) {
240 proc_busy = sampler.GetProcessLoad();
241 }
242 if (test_sys) {
243 sys_busy = sampler.GetSystemLoad();
244 }
245 if (test_proc) {
246 LOG(LS_INFO) << "ProcessLoad Busy: "
247 << std::setiosflags(std::ios_base::fixed)
248 << std::setprecision(2) << std::setw(6) << proc_busy;
249 EXPECT_GE(proc_busy, 0.f);
250 EXPECT_LE(proc_busy, static_cast<float>(cpus));
251 }
252 if (test_sys) {
253 LOG(LS_INFO) << "SystemLoad Busy: "
254 << std::setiosflags(std::ios_base::fixed)
255 << std::setprecision(2) << std::setw(6) << sys_busy;
256 EXPECT_GE(sys_busy, 0.f);
257 EXPECT_LE(sys_busy, static_cast<float>(cpus));
258 }
259
260 // Test4: CpuSampler with 2 cpus process busy.
261 if (cpus >= 2) {
262 Thread::SleepMs(kSettleTime);
263 sampler.GetProcessLoad();
264 sampler.GetSystemLoad();
265
266 CpuTwoBusyLoop(kBusyTime);
267
268 float proc_twobusy = 0.f, sys_twobusy = 0.f;
269 if (test_proc) {
270 proc_twobusy = sampler.GetProcessLoad();
271 }
272 if (test_sys) {
273 sys_twobusy = sampler.GetSystemLoad();
274 }
275 if (test_proc) {
276 LOG(LS_INFO) << "ProcessLoad 2 CPU Busy:"
277 << std::setiosflags(std::ios_base::fixed)
278 << std::setprecision(2) << std::setw(6) << proc_twobusy;
279 EXPECT_GE(proc_twobusy, 0.f);
280 EXPECT_LE(proc_twobusy, static_cast<float>(cpus));
281 }
282 if (test_sys) {
283 LOG(LS_INFO) << "SystemLoad 2 CPU Busy: "
284 << std::setiosflags(std::ios_base::fixed)
285 << std::setprecision(2) << std::setw(6) << sys_twobusy;
286 EXPECT_GE(sys_twobusy, 0.f);
287 EXPECT_LE(sys_twobusy, static_cast<float>(cpus));
288 }
289 }
290
291 // Test5: CpuSampler with idle process after being busy.
292 Thread::SleepMs(kSettleTime);
293 sampler.GetProcessLoad();
294 sampler.GetSystemLoad();
295
296 Thread::SleepMs(kIdleTime);
297
298 if (test_proc) {
299 proc_idle = sampler.GetProcessLoad();
300 }
301 if (test_sys) {
302 sys_idle = sampler.GetSystemLoad();
303 }
304 if (test_proc) {
305 LOG(LS_INFO) << "ProcessLoad Idle: "
306 << std::setiosflags(std::ios_base::fixed)
307 << std::setprecision(2) << std::setw(6) << proc_idle;
308 EXPECT_GE(proc_idle, 0.f);
309 EXPECT_LE(proc_idle, proc_busy);
310 }
311 if (test_sys) {
312 LOG(LS_INFO) << "SystemLoad Idle: "
313 << std::setiosflags(std::ios_base::fixed)
314 << std::setprecision(2) << std::setw(6) << sys_idle;
315 EXPECT_GE(sys_idle, 0.f);
316 EXPECT_LE(sys_idle, static_cast<float>(cpus));
317 }
318 }
319
320 TEST(CpuMonitorTest, TestCpus) {
321 CpuSampler sampler;
322 EXPECT_TRUE(sampler.Init());
323 int current_cpus = sampler.GetCurrentCpus();
324 int cpus = sampler.GetMaxCpus();
325 LOG(LS_INFO) << "Current Cpus: " << std::setw(9) << current_cpus;
326 LOG(LS_INFO) << "Maximum Cpus: " << std::setw(9) << cpus;
327 EXPECT_GT(cpus, 0);
328 EXPECT_LE(cpus, kMaxCpus);
329 EXPECT_GT(current_cpus, 0);
330 EXPECT_LE(current_cpus, cpus);
331 }
332
333 #if defined(WEBRTC_WIN)
334 // Tests overall system CpuSampler using legacy OS fallback code if applicable.
335 TEST(CpuMonitorTest, TestGetSystemLoadForceFallback) {
336 TestCpuSampler(false, true, true);
337 }
338 #endif
339
340 // Tests both process and system functions in use at same time.
341 TEST(CpuMonitorTest, TestGetBothLoad) {
342 TestCpuSampler(true, true, false);
343 }
344
345 // Tests a query less than the interval produces the same value.
346 TEST(CpuMonitorTest, TestInterval) {
347 CpuSampler sampler;
348 EXPECT_TRUE(sampler.Init());
349
350 // Test1: Set interval to large value so sampler will not update.
351 sampler.set_load_interval(kLongInterval);
352
353 sampler.GetProcessLoad();
354 sampler.GetSystemLoad();
355
356 float proc_orig = sampler.GetProcessLoad();
357 float sys_orig = sampler.GetSystemLoad();
358
359 Thread::SleepMs(kIdleTime);
360
361 float proc_halftime = sampler.GetProcessLoad();
362 float sys_halftime = sampler.GetSystemLoad();
363
364 EXPECT_EQ(proc_orig, proc_halftime);
365 EXPECT_EQ(sys_orig, sys_halftime);
366 }
367
368 TEST(CpuMonitorTest, TestCpuMonitor) {
369 CpuMonitor monitor(Thread::Current());
370 CpuLoadListener listener;
371 monitor.SignalUpdate.connect(&listener, &CpuLoadListener::OnCpuLoad);
372 EXPECT_TRUE(monitor.Start(10));
373 // We have checked cpu load more than twice.
374 EXPECT_TRUE_WAIT(listener.count() > 2, 1000);
375 EXPECT_GT(listener.current_cpus(), 0);
376 EXPECT_GT(listener.cpus(), 0);
377 EXPECT_GE(listener.process_load(), .0f);
378 EXPECT_GE(listener.system_load(), .0f);
379
380 monitor.Stop();
381 // Wait 20 ms to ake sure all signals are delivered.
382 Thread::Current()->ProcessMessages(20);
383 int old_count = listener.count();
384 Thread::Current()->ProcessMessages(20);
385 // Verfy no more siganls.
386 EXPECT_EQ(old_count, listener.count());
387 }
388
389 } // namespace rtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/base/platform_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698