1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#include "config.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <errno.h>
static int fake_gettimeofday(struct timeval *tv, struct timezone *tz);
static int fake_getrusage(int who, struct rusage *usage);
#define gettimeofday fake_gettimeofday
#define getrusage fake_getrusage
#include <ccan/lbalance/lbalance.c>
#include <ccan/tap/tap.h>
static unsigned faketime_ms = 0;
static struct rusage total_usage;
static int fake_gettimeofday(struct timeval *tv, struct timezone *tz)
{
assert(tz == NULL);
tv->tv_usec = (faketime_ms % 1000) * 1000;
tv->tv_sec = faketime_ms / 1000;
return 0;
}
static int fake_getrusage(int who, struct rusage *usage)
{
assert(who == RUSAGE_CHILDREN);
*usage = total_usage;
return 0;
}
static void test_optimum(struct lbalance *lb, unsigned int optimum)
{
unsigned int j, i, num_tasks = 0, usec, num_counted = 0;
float average;
struct lbalance_task *tasks[1000];
for (j = 0; j < 1000; j++) {
diag("lbalance_target is %u\n", lbalance_target(lb));
/* We measure average once we try optimum once. */
if (lbalance_target(lb) == optimum && num_counted == 0) {
average = lbalance_target(lb);
num_counted = 1;
} else if (num_counted) {
average += lbalance_target(lb);
num_counted++;
}
/* Create tasks until we reach target. */
for (i = 0; i < lbalance_target(lb); i++) {
tasks[i] = lbalance_task_new(lb);
}
num_tasks = i;
faketime_ms += 100;
/* If we're under optimum, set utilization to 100% */
if (num_tasks <= optimum) {
usec = 100000;
} else {
usec = 100000 * optimum / num_tasks;
}
for (i = 0; i < num_tasks; i++) {
total_usage.ru_utime.tv_usec += usec / 2;
if (total_usage.ru_utime.tv_usec > 1000000) {
total_usage.ru_utime.tv_usec -= 1000000;
total_usage.ru_utime.tv_sec++;
}
total_usage.ru_stime.tv_usec += usec / 2;
if (total_usage.ru_stime.tv_usec > 1000000) {
total_usage.ru_stime.tv_usec -= 1000000;
total_usage.ru_stime.tv_sec++;
}
lbalance_task_free(tasks[i], NULL);
}
}
/* We should have stayed close to optimum. */
ok1(num_counted && (int)(average / num_counted + 0.5) == optimum);
}
int main(void)
{
struct lbalance *lb;
plan_tests(4);
lb = lbalance_new();
test_optimum(lb, 1);
test_optimum(lb, 2);
test_optimum(lb, 4);
test_optimum(lb, 64);
lbalance_free(lb);
return exit_status();
}
|