benchmark filter
[libc-test] / common / b.c
index b82531c..6c9fb19 100644 (file)
@@ -1,4 +1,3 @@
-#define _POSIX_C_SOURCE 200809L
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -9,30 +8,31 @@
 #include <unistd.h>
 #include "test.h"
 
-#define T(t)
-#define B(t) void t();
-#include "main.h"
+#define T(f)
+#define B(f) void f(int);
+#include "tests.h"
 #undef B
 
 static int verbose = 1;
 
 void error__(const char *n, int l, const char *s, ...) {
-       fprintf(stderr, "use error in tests only\n");
+       dprintf(1, "use error in tests only\n");
 }
 
-int N;
+static int N;
 static unsigned long long start;
 static unsigned long long dt;
 //static unsigned long long bytes;
 
 #define SEC  1000000000ULL
 #define MAXN  500000000
+#define MINT (SEC/5)
 
 static unsigned long long tic() {
        struct timespec ts;
 
-       if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
-               fprintf(stderr, "bench: clock_gettime failed: %s\n", strerror(errno));
+       if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
+               dprintf(1, "bench: clock_gettime failed: %s\n", strerror(errno));
                return 0;
        }
        return ts.tv_sec*SEC + ts.tv_nsec;
@@ -57,11 +57,12 @@ void reset_timer() {
 
 static int nextN() {
        unsigned long long n = dt/N;
+       unsigned long long i;
 
        if (n)
-               n = SEC/2/n;
+               n = MINT/n;
        else
-               n = SEC/2;
+               n = MINT;
        n += n/2;
        if (n > N*100ULL)
                n = N*100ULL;
@@ -69,7 +70,14 @@ static int nextN() {
                n = N+1;
        if (n > MAXN)
                n = MAXN;
-       return n;
+
+       /* round up to a nice number */
+       for (i = 1; i < n; i *= 10);
+       if (i/2 >= n)
+               i /= 2;
+       if (i/2 >= n)
+               i /= 2;
+       return i;
 }
 
 void vmstats() {
@@ -81,7 +89,7 @@ void vmstats() {
 
        f = fopen("/proc/self/smaps", "rb");
        if (f) while (fgets(buf, sizeof buf, f)) {
-               if (sscanf(buf, "%*lx-%*lx %*s %*lx %x:%x %*lu %*s", &maj, &min)==2)
+               if (sscanf(buf, "%*x-%*x %*s %*x %x:%x %*u %*s", &maj, &min)==2)
                        in_heap = (!maj && !min && !strstr(buf, "---p") && (strstr(buf, "[heap]") || !strchr(buf, '[')));
                if (in_heap) {
                        if (sscanf(buf, "Size: %lu", &l)==1) vm_size += l;
@@ -90,47 +98,74 @@ void vmstats() {
                }
        }
        if (f) fclose(f);
-       fprintf(stderr, " %7zu virt %7zu res %7zu dirty", vm_size, vm_rss, vm_priv_dirty);
+       dprintf(1, " %7zu virt %7zu res %7zu dirty", vm_size, vm_rss, vm_priv_dirty);
 }
 
 void stats() {
-       if (dt/N > 100)
-               fprintf(stderr, "%10d N %10llu ns/op   ", N, dt/N);
+       if (dt/N >= 100)
+               dprintf(1, "%10d N %10llu ns/op   ", N, dt/N);
        else
-               fprintf(stderr, "%10d N %13.2f ns/op", N, (double)dt/N);
+               dprintf(1, "%10d N %13.2f ns/op", N, (double)dt/N);
        if (verbose)
                vmstats();
-       fputc('\n', stderr);
+       dprintf(1, "\n");
 }
 
-static void run(const char *name, void (*f)()) {
-       int p = fork();
+static char *pattern;
+
+static void run(const char *name, void (*f)(int)) {
+       int p;
+
+       if (pattern && !strstr(name, pattern))
+               return;
+       p = fork();
        if (p) {
                int s;
                if (p<0 || wait(&s)<0 || !WIFEXITED(s) || WEXITSTATUS(s))
-                       fprintf(stderr, "benchmark %s failed\n", name);
+                       dprintf(1, "benchmark %s failed\n", name);
                return;
        }
-       fprintf(stderr, "%-32s", name);
+       dprintf(1, "%-32s", name);
        for (N=1; ; N=nextN()) {
+               // TODO: fork at each iteration and pass N,dt..?
                reset_timer();
                start_timer();
-               f();
+               f(N);
                stop_timer();
-//             fprintf(stderr, "%10d%12llu next: %d\n", N, dt, nextN());
+//             dprintf(1, "%10d%12llu next: %d\n", N, dt, nextN());
                if (dt >= SEC/2 || N >= MAXN) {
                        stats();
                        exit(0);
                }
                if (N <= 0) {
-                       fprintf(stderr, "bench: fatal: N <= 0\n");
+                       dprintf(1, "bench: fatal: N <= 0\n");
                        exit(1);
                }
        }
 }
 
-int main() {
+static void usage() {
+       fprintf(stderr, "usage: ./t [-vq] [pat]\n");
+       exit(1);
+}
+
+int main(int argc, char *argv[]) {
+       int c;
+
+       while((c = getopt(argc, argv, "vq")) != -1)
+               switch(c) {
+               case 'v':
+                       verbose = 1;
+                       break;
+               case 'q':
+                       verbose = 0;
+                       break;
+               default:
+                       usage();
+               }
+       if (optind != argc)
+               pattern = argv[optind];
 #define B(t) run(#t, t);
-#include "main.h"
+#include "tests.h"
        return 0;
 }