Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / base / cpumonitor_unittest.cc
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, DISABLED_ON_MAC(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