]> git.ozlabs.org Git - ccan/blobdiff - ccan/lbalance/tools/lbalance.c
lbalance: new module for load balancing
[ccan] / ccan / lbalance / tools / lbalance.c
diff --git a/ccan/lbalance/tools/lbalance.c b/ccan/lbalance/tools/lbalance.c
new file mode 100644 (file)
index 0000000..228c947
--- /dev/null
@@ -0,0 +1,117 @@
+#include <ccan/lbalance/lbalance.h>
+#include <ccan/lbalance/lbalance.c>
+#include <ccan/time/time.h>
+#include <ccan/jmap/jmap_type.h>
+#include <stdio.h>
+#include <err.h>
+
+/* Defines struct jmap_task. */
+JMAP_DEFINE_UINTIDX_TYPE(struct lbalance_task, task);
+
+/* Figure out how many loops we need to run for about 1 second. */
+static unsigned long burn_count;
+
+static void calibrate_burn_cpu(void)
+{
+       struct timeval start = time_now();
+
+       while (time_less(time_now(), time_add(start, time_from_msec(1000))))
+               burn_count++;
+       printf("Burn count = %lu\n", burn_count);
+}
+
+static void burn_cpu(void)
+{
+       unsigned int i, after = 0;
+       struct timeval start = time_now();
+
+       /* We do a loop similar to the calibrate_burn_cpu loop. */ 
+       for (i = 0; i < burn_count; i++) {
+               after += time_less(time_now(),
+                                  time_add(start, time_from_msec(1000)));
+       }
+       /* We use the result so the compiler can't discard it. */
+       exit(after);
+}
+
+static pid_t spawn(char *args[])
+{
+       pid_t pid = fork();
+
+       if (pid == -1)
+               err(1, "forking");
+       if (pid == 0) {
+               if (!args[0])
+                       burn_cpu();
+               execvp(args[0], args);
+               err(1, "exec failed");
+       }
+       return pid;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i, num, fixed_target = 0, num_done = 0, num_running = 0;
+       struct lbalance *lb;
+       struct jmap_task *tasks = jmap_task_new();
+
+       if (argc < 2) {
+               fprintf(stderr,
+                       "Usage: lbalance --fixed=<num> <num> [<command>...]\n"
+                       "OR: lbalance <num> [<command>...]\n");
+               exit(1);
+       }
+
+       if (strncmp(argv[1], "--fixed=", strlen("--fixed=")) == 0) {
+               fixed_target = atoi(argv[1] + strlen("--fixed="));
+               if (!fixed_target)
+                       errx(1, "Need positive number after --fixed");
+               argv++;
+               argc--;
+               lb = NULL;
+       } else {
+               lb = lbalance_new();
+       }
+       num = atoi(argv[1]);
+       argv++;
+       argc--;
+
+       if (!argv[1])
+               calibrate_burn_cpu();
+
+       while (num_done < num) {
+               unsigned int j, target = fixed_target;
+               struct lbalance_task *task;
+               struct rusage ru;
+               pid_t pid;
+
+               if (lb) {
+                       target = lbalance_target(lb);
+                       printf("(%u)", target);
+               }
+
+               while (num_running < target && num_done + num_running < num) {
+                       pid = spawn(argv+1);
+                       if (lb)
+                               task = lbalance_task_new(lb);
+                       else
+                               task = (void *)1;
+                       jmap_task_add(tasks, pid, task);
+                       num_running++;
+                       printf("+"); fflush(stdout);
+               }
+
+               /* Now wait for something to die! */
+               pid = wait3(NULL, 0, &ru);
+               task = jmap_task_get(tasks, pid);
+               if (lb)
+                       lbalance_task_free(task, &ru);
+               num_done++;
+               num_running--;
+               printf("-"); fflush(stdout);
+       }
+       printf("\n");
+       if (lb)
+               lbalance_free(lb);
+       return 0;
+}