~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/googletalk/libjingle/talk/base/cpumonitor_unittest.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * libjingle
3
 
 * Copyright 2010 Google Inc.
4
 
 *
5
 
 * Redistribution and use in source and binary forms, with or without
6
 
 * modification, are permitted provided that the following conditions are met:
7
 
 *
8
 
 *  1. Redistributions of source code must retain the above copyright notice,
9
 
 *     this list of conditions and the following disclaimer.
10
 
 *  2. Redistributions in binary form must reproduce the above copyright notice,
11
 
 *     this list of conditions and the following disclaimer in the documentation
12
 
 *     and/or other materials provided with the distribution.
13
 
 *  3. The name of the author may not be used to endorse or promote products
14
 
 *     derived from this software without specific prior written permission.
15
 
 *
16
 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
 
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 
 */
27
 
 
28
 
#include <iomanip>
29
 
#include <iostream>
30
 
#include <vector>
31
 
 
32
 
#ifdef WIN32
33
 
#include "talk/base/win32.h"
34
 
#endif
35
 
 
36
 
#include "talk/base/cpumonitor.h"
37
 
#include "talk/base/flags.h"
38
 
#include "talk/base/gunit.h"
39
 
#include "talk/base/scoped_ptr.h"
40
 
#include "talk/base/thread.h"
41
 
#include "talk/base/timeutils.h"
42
 
#include "talk/base/timing.h"
43
 
 
44
 
namespace talk_base {
45
 
 
46
 
static const int kMaxCpus = 1024;
47
 
static const int kSettleTime = 100;  // Amount of time to between tests.
48
 
static const int kIdleTime = 500;  // Amount of time to be idle in ms.
49
 
static const int kBusyTime = 1000;  // Amount of time to be busy in ms.
50
 
static const int kLongInterval = 2000;  // Interval longer than busy times
51
 
 
52
 
class BusyThread : public talk_base::Thread {
53
 
 public:
54
 
  BusyThread(double load, double duration, double interval) :
55
 
    load_(load), duration_(duration), interval_(interval) {
56
 
  }
57
 
  void Run() {
58
 
    Timing time;
59
 
    double busy_time = interval_ * load_ / 100.0;
60
 
    for (;;) {
61
 
      time.BusyWait(busy_time);
62
 
      time.IdleWait(interval_ - busy_time);
63
 
      if (duration_) {
64
 
        duration_ -= interval_;
65
 
        if (duration_ <= 0) {
66
 
          break;
67
 
        }
68
 
      }
69
 
    }
70
 
  }
71
 
 private:
72
 
  double load_;
73
 
  double duration_;
74
 
  double interval_;
75
 
};
76
 
 
77
 
class CpuLoadListener : public sigslot::has_slots<> {
78
 
 public:
79
 
  CpuLoadListener()
80
 
      : current_cpus_(0),
81
 
        cpus_(0),
82
 
        process_load_(.0f),
83
 
        system_load_(.0f),
84
 
        count_(0) {
85
 
  }
86
 
 
87
 
  void OnCpuLoad(int current_cpus, int cpus, float proc_load, float sys_load) {
88
 
    current_cpus_ = current_cpus;
89
 
    cpus_ = cpus;
90
 
    process_load_ = proc_load;
91
 
    system_load_ = sys_load;
92
 
    ++count_;
93
 
  }
94
 
 
95
 
  int current_cpus() const { return current_cpus_; }
96
 
  int cpus() const { return cpus_; }
97
 
  float process_load() const { return process_load_; }
98
 
  float system_load() const { return system_load_; }
99
 
  int count() const { return count_; }
100
 
 
101
 
 private:
102
 
  int current_cpus_;
103
 
  int cpus_;
104
 
  float process_load_;
105
 
  float system_load_;
106
 
  int count_;
107
 
};
108
 
 
109
 
// Set affinity (which cpu to run on), but respecting FLAG_affinity:
110
 
// -1 means no affinity - run on whatever cpu is available.
111
 
// 0 .. N means run on specific cpu.  The tool will create N threads and call
112
 
//   SetThreadAffinity on 0 to N - 1 as cpu.  FLAG_affinity sets the first cpu
113
 
//   so the range becomes affinity to affinity + N - 1
114
 
// Note that this function affects Windows scheduling, effectively giving
115
 
//   the thread with affinity for a specified CPU more priority on that CPU.
116
 
bool SetThreadAffinity(BusyThread* t, int cpu, int affinity) {
117
 
#ifdef WIN32
118
 
  if (affinity >= 0) {
119
 
    return ::SetThreadAffinityMask(t->GetHandle(),
120
 
        1 << (cpu + affinity)) != FALSE;
121
 
  }
122
 
#endif
123
 
  return true;
124
 
}
125
 
 
126
 
bool SetThreadPriority(BusyThread* t, int prio) {
127
 
  if (!prio) {
128
 
    return true;
129
 
  }
130
 
  bool ok = t->SetPriority(static_cast<talk_base::ThreadPriority>(prio));
131
 
  if (!ok) {
132
 
    std::cout << "Error setting thread priority." << std::endl;
133
 
  }
134
 
  return ok;
135
 
}
136
 
 
137
 
int CpuLoad(double cpuload, double duration, int numthreads,
138
 
            int priority, double interval, int affinity) {
139
 
  int ret = 0;
140
 
  std::vector<BusyThread*> threads;
141
 
  for (int i = 0; i < numthreads; ++i) {
142
 
    threads.push_back(new BusyThread(cpuload, duration, interval));
143
 
    // NOTE(fbarchard): Priority must be done before Start.
144
 
    if (!SetThreadPriority(threads[i], priority) ||
145
 
       !threads[i]->Start() ||
146
 
       !SetThreadAffinity(threads[i], i, affinity)) {
147
 
      ret = 1;
148
 
      break;
149
 
    }
150
 
  }
151
 
  // Wait on each thread
152
 
  if (ret == 0) {
153
 
    for (int i = 0; i < numthreads; ++i) {
154
 
      threads[i]->Stop();
155
 
    }
156
 
  }
157
 
 
158
 
  for (int i = 0; i < numthreads; ++i) {
159
 
    delete threads[i];
160
 
  }
161
 
  return ret;
162
 
}
163
 
 
164
 
// Make 2 CPUs busy
165
 
static void CpuTwoBusyLoop(int busytime) {
166
 
  CpuLoad(100.0, busytime / 1000.0, 2, 1, 0.050, -1);
167
 
}
168
 
 
169
 
// Make 1 CPUs busy
170
 
static void CpuBusyLoop(int busytime) {
171
 
  CpuLoad(100.0, busytime / 1000.0, 1, 1, 0.050, -1);
172
 
}
173
 
 
174
 
// Make 1 use half CPU time.
175
 
static void CpuHalfBusyLoop(int busytime) {
176
 
  CpuLoad(50.0, busytime / 1000.0, 1, 1, 0.050, -1);
177
 
}
178
 
 
179
 
void TestCpuSampler(bool test_proc, bool test_sys, bool force_fallback) {
180
 
  CpuSampler sampler;
181
 
  sampler.set_force_fallback(force_fallback);
182
 
  EXPECT_TRUE(sampler.Init());
183
 
  sampler.set_load_interval(100);
184
 
  int cpus = sampler.GetMaxCpus();
185
 
 
186
 
  // Test1: CpuSampler under idle situation.
187
 
  Thread::SleepMs(kSettleTime);
188
 
  sampler.GetProcessLoad();
189
 
  sampler.GetSystemLoad();
190
 
 
191
 
  Thread::SleepMs(kIdleTime);
192
 
 
193
 
  float proc_idle = 0.f, sys_idle = 0.f;
194
 
  if (test_proc) {
195
 
    proc_idle = sampler.GetProcessLoad();
196
 
  }
197
 
  if (test_sys) {
198
 
      sys_idle = sampler.GetSystemLoad();
199
 
  }
200
 
  if (test_proc) {
201
 
    LOG(LS_INFO) << "ProcessLoad Idle:      "
202
 
                 << setiosflags(std::ios_base::fixed)
203
 
                 << std::setprecision(2) << std::setw(6) << proc_idle;
204
 
    EXPECT_GE(proc_idle, 0.f);
205
 
    EXPECT_LE(proc_idle, static_cast<float>(cpus));
206
 
  }
207
 
  if (test_sys) {
208
 
    LOG(LS_INFO) << "SystemLoad Idle:       "
209
 
                 << setiosflags(std::ios_base::fixed)
210
 
                 << std::setprecision(2) << std::setw(6) << sys_idle;
211
 
    EXPECT_GE(sys_idle, 0.f);
212
 
    EXPECT_LE(sys_idle, static_cast<float>(cpus));
213
 
  }
214
 
 
215
 
  // Test2: CpuSampler with main process at 50% busy.
216
 
  Thread::SleepMs(kSettleTime);
217
 
  sampler.GetProcessLoad();
218
 
  sampler.GetSystemLoad();
219
 
 
220
 
  CpuHalfBusyLoop(kBusyTime);
221
 
 
222
 
  float proc_halfbusy = 0.f, sys_halfbusy = 0.f;
223
 
  if (test_proc) {
224
 
    proc_halfbusy = sampler.GetProcessLoad();
225
 
  }
226
 
  if (test_sys) {
227
 
    sys_halfbusy = sampler.GetSystemLoad();
228
 
  }
229
 
  if (test_proc) {
230
 
    LOG(LS_INFO) << "ProcessLoad Halfbusy:  "
231
 
                 << setiosflags(std::ios_base::fixed)
232
 
                 << std::setprecision(2) << std::setw(6) << proc_halfbusy;
233
 
    EXPECT_GE(proc_halfbusy, 0.f);
234
 
    EXPECT_LE(proc_halfbusy, static_cast<float>(cpus));
235
 
  }
236
 
  if (test_sys) {
237
 
    LOG(LS_INFO) << "SystemLoad Halfbusy:   "
238
 
                 << setiosflags(std::ios_base::fixed)
239
 
                 << std::setprecision(2) << std::setw(6) << sys_halfbusy;
240
 
    EXPECT_GE(sys_halfbusy, 0.f);
241
 
    EXPECT_LE(sys_halfbusy, static_cast<float>(cpus));
242
 
  }
243
 
 
244
 
  // Test3: CpuSampler with main process busy.
245
 
  Thread::SleepMs(kSettleTime);
246
 
  sampler.GetProcessLoad();
247
 
  sampler.GetSystemLoad();
248
 
 
249
 
  CpuBusyLoop(kBusyTime);
250
 
 
251
 
  float proc_busy = 0.f, sys_busy = 0.f;
252
 
  if (test_proc) {
253
 
    proc_busy = sampler.GetProcessLoad();
254
 
  }
255
 
  if (test_sys) {
256
 
    sys_busy = sampler.GetSystemLoad();
257
 
  }
258
 
  if (test_proc) {
259
 
    LOG(LS_INFO) << "ProcessLoad Busy:      "
260
 
                 << setiosflags(std::ios_base::fixed)
261
 
                 << std::setprecision(2) << std::setw(6) << proc_busy;
262
 
    EXPECT_GE(proc_busy, 0.f);
263
 
    EXPECT_LE(proc_busy, static_cast<float>(cpus));
264
 
  }
265
 
  if (test_sys) {
266
 
    LOG(LS_INFO) << "SystemLoad Busy:       "
267
 
                 << setiosflags(std::ios_base::fixed)
268
 
                 << std::setprecision(2) << std::setw(6) << sys_busy;
269
 
    EXPECT_GE(sys_busy, 0.f);
270
 
    EXPECT_LE(sys_busy, static_cast<float>(cpus));
271
 
  }
272
 
 
273
 
  // Test4: CpuSampler with 2 cpus process busy.
274
 
  if (cpus >= 2) {
275
 
    Thread::SleepMs(kSettleTime);
276
 
    sampler.GetProcessLoad();
277
 
    sampler.GetSystemLoad();
278
 
 
279
 
    CpuTwoBusyLoop(kBusyTime);
280
 
 
281
 
    float proc_twobusy = 0.f, sys_twobusy = 0.f;
282
 
    if (test_proc) {
283
 
      proc_twobusy = sampler.GetProcessLoad();
284
 
    }
285
 
    if (test_sys) {
286
 
      sys_twobusy = sampler.GetSystemLoad();
287
 
    }
288
 
    if (test_proc) {
289
 
      LOG(LS_INFO) << "ProcessLoad 2 CPU Busy:"
290
 
                   << setiosflags(std::ios_base::fixed)
291
 
                   << std::setprecision(2) << std::setw(6) << proc_twobusy;
292
 
      EXPECT_GE(proc_twobusy, 0.f);
293
 
      EXPECT_LE(proc_twobusy, static_cast<float>(cpus));
294
 
    }
295
 
    if (test_sys) {
296
 
      LOG(LS_INFO) << "SystemLoad 2 CPU Busy: "
297
 
                   << setiosflags(std::ios_base::fixed)
298
 
                   << std::setprecision(2) << std::setw(6) << sys_twobusy;
299
 
      EXPECT_GE(sys_twobusy, 0.f);
300
 
      EXPECT_LE(sys_twobusy, static_cast<float>(cpus));
301
 
    }
302
 
  }
303
 
 
304
 
  // Test5: CpuSampler with idle process after being busy.
305
 
  Thread::SleepMs(kSettleTime);
306
 
  sampler.GetProcessLoad();
307
 
  sampler.GetSystemLoad();
308
 
 
309
 
  Thread::SleepMs(kIdleTime);
310
 
 
311
 
  if (test_proc) {
312
 
    proc_idle = sampler.GetProcessLoad();
313
 
  }
314
 
  if (test_sys) {
315
 
    sys_idle = sampler.GetSystemLoad();
316
 
  }
317
 
  if (test_proc) {
318
 
    LOG(LS_INFO) << "ProcessLoad Idle:      "
319
 
                 << setiosflags(std::ios_base::fixed)
320
 
                 << std::setprecision(2) << std::setw(6) << proc_idle;
321
 
    EXPECT_GE(proc_idle, 0.f);
322
 
    EXPECT_LE(proc_idle, proc_busy);
323
 
  }
324
 
  if (test_sys) {
325
 
    LOG(LS_INFO) << "SystemLoad Idle:       "
326
 
                 << setiosflags(std::ios_base::fixed)
327
 
                 << std::setprecision(2) << std::setw(6) << sys_idle;
328
 
    EXPECT_GE(sys_idle, 0.f);
329
 
    EXPECT_LE(sys_idle, static_cast<float>(cpus));
330
 
  }
331
 
}
332
 
 
333
 
TEST(CpuMonitorTest, TestCpus) {
334
 
  CpuSampler sampler;
335
 
  EXPECT_TRUE(sampler.Init());
336
 
  int current_cpus = sampler.GetCurrentCpus();
337
 
  int cpus = sampler.GetMaxCpus();
338
 
  LOG(LS_INFO) << "Current Cpus:     " << std::setw(9) << current_cpus;
339
 
  LOG(LS_INFO) << "Maximum Cpus:     " << std::setw(9) << cpus;
340
 
  EXPECT_GT(cpus, 0);
341
 
  EXPECT_LE(cpus, kMaxCpus);
342
 
  EXPECT_GT(current_cpus, 0);
343
 
  EXPECT_LE(current_cpus, cpus);
344
 
}
345
 
 
346
 
#ifdef WIN32
347
 
// Tests overall system CpuSampler using legacy OS fallback code if applicable.
348
 
TEST(CpuMonitorTest, TestGetSystemLoadForceFallback) {
349
 
  TestCpuSampler(false, true, true);
350
 
}
351
 
#endif
352
 
 
353
 
// Tests both process and system functions in use at same time.
354
 
TEST(CpuMonitorTest, TestGetBothLoad) {
355
 
  TestCpuSampler(true, true, false);
356
 
}
357
 
 
358
 
// Tests a query less than the interval produces the same value.
359
 
TEST(CpuMonitorTest, TestInterval) {
360
 
  CpuSampler sampler;
361
 
  EXPECT_TRUE(sampler.Init());
362
 
 
363
 
  // Test1: Set interval to large value so sampler will not update.
364
 
  sampler.set_load_interval(kLongInterval);
365
 
 
366
 
  sampler.GetProcessLoad();
367
 
  sampler.GetSystemLoad();
368
 
 
369
 
  float proc_orig = sampler.GetProcessLoad();
370
 
  float sys_orig = sampler.GetSystemLoad();
371
 
 
372
 
  Thread::SleepMs(kIdleTime);
373
 
 
374
 
  float proc_halftime = sampler.GetProcessLoad();
375
 
  float sys_halftime = sampler.GetSystemLoad();
376
 
 
377
 
  EXPECT_EQ(proc_orig, proc_halftime);
378
 
  EXPECT_EQ(sys_orig, sys_halftime);
379
 
}
380
 
 
381
 
TEST(CpuMonitorTest, TestCpuMonitor) {
382
 
  CpuMonitor monitor(Thread::Current());
383
 
  CpuLoadListener listener;
384
 
  monitor.SignalUpdate.connect(&listener, &CpuLoadListener::OnCpuLoad);
385
 
  EXPECT_TRUE(monitor.Start(10));
386
 
  Thread::Current()->ProcessMessages(50);
387
 
  EXPECT_GT(listener.count(), 2);  // We have checked cpu load more than twice.
388
 
  EXPECT_GT(listener.current_cpus(), 0);
389
 
  EXPECT_GT(listener.cpus(), 0);
390
 
  EXPECT_GE(listener.process_load(), .0f);
391
 
  EXPECT_GE(listener.system_load(), .0f);
392
 
 
393
 
  monitor.Stop();
394
 
  // Wait 20 ms to ake sure all signals are delivered.
395
 
  Thread::Current()->ProcessMessages(20);
396
 
  int old_count = listener.count();
397
 
  Thread::Current()->ProcessMessages(20);
398
 
  // Verfy no more siganls.
399
 
  EXPECT_EQ(old_count, listener.count());
400
 
}
401
 
 
402
 
}  // namespace talk_base