benchmark.c (2929B)
1 #include <stdint.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #if defined(_WIN32) || defined(_WIN64) 7 #include "win32ports/time.h" 8 #else 9 #include <sys/time.h> 10 #endif 11 12 #include "benchmark.h" 13 14 struct bmark_queue_t { 15 void *next; 16 char *name; 17 void (*fn)(); 18 }; 19 struct bmark_ptile_t { 20 char n; 21 }; 22 23 struct bmark_queue_t *bmark_queue = NULL; 24 25 struct bmark_unit_entry { 26 char *name; 27 int next; 28 }; 29 30 struct bmark_unit_entry units[] = { 31 { "us", 1000 }, 32 { "ms", 1000 }, 33 { "s" , 60 }, 34 { "m" , 0 }, 35 }; 36 37 const char *header_description = "Description"; 38 39 void bmark_enqueue(char *name, void (*fn)()) { 40 struct bmark_queue_t *q = calloc(1, sizeof(struct bmark_queue_t)); 41 q->name = name; 42 q->fn = fn; 43 q->next = bmark_queue; 44 bmark_queue = q; 45 } 46 47 // Example time numbers: 12.23 s 48 // 900.00 ms 49 // 123.45 us 50 int bmark_run(int run_count, char percentiles[]) { 51 int header_desclen = strlen(header_description); 52 int i, l, r, unit; 53 struct timeval tv_start; 54 struct timeval tv_end; 55 56 uint64_t *runs = calloc(run_count, sizeof(uint64_t)); 57 uint64_t run_tmp = 0; 58 double run_f = 0; 59 60 // Get max description length 61 struct bmark_queue_t *q_entry = bmark_queue; 62 while(q_entry) { 63 l = strlen(q_entry->name); 64 if (l > header_desclen) header_desclen = l; 65 q_entry = q_entry->next; 66 } 67 68 printf("\n"); 69 70 // Column names 71 printf("| %-*s |", header_desclen, header_description); 72 for(i = 0 ; percentiles[i] ; i++) printf(" %*d %% |", 7, percentiles[i]); 73 printf("\n"); 74 75 // Separator 76 printf("|:"); 77 for(i = 0 ; i < header_desclen ; i++) printf("-"); 78 printf(" |"); 79 for(i = 0 ; percentiles[i] ; i++) printf(" ---------:|"); 80 printf("\n"); 81 82 // Go over the whole queue 83 q_entry = bmark_queue; 84 while(q_entry) { 85 printf("| %-*s |", header_desclen, q_entry->name); 86 fflush(stdout); 87 88 // Do the actual runs 89 for(r = 0; r < run_count ; r++) { 90 gettimeofday(&tv_start, NULL); 91 q_entry->fn(); 92 gettimeofday(&tv_end, NULL); 93 runs[r] = (tv_end.tv_sec*(uint64_t)1000000+tv_end.tv_usec) - (tv_start.tv_sec*(uint64_t)1000000+tv_start.tv_usec); 94 } 95 96 // Sort the runs 97 // Basic bubble sort is fine here, we're not going for a speed record 98 for(r = 0; r < (run_count-1) ; r++) { 99 if (r < 0) continue; 100 if (runs[r] > runs[r+1]) { 101 run_tmp = runs[r]; 102 runs[r] = runs[r+1]; 103 runs[r+1] = run_tmp; 104 r -= 2; 105 } 106 } 107 108 // Print percentiles 109 for(i = 0 ; percentiles[i] ; i++) { 110 r = percentiles[i] * (run_count-1) / 100; 111 run_f = (double)runs[r]; 112 unit = 0; 113 while((run_f > units[unit].next) && units[unit].next) { 114 run_f = run_f / units[unit].next; 115 unit++; 116 } 117 printf(" %*.2lf %2s |", 6, run_f, units[unit].name); 118 } 119 120 printf("\n"); 121 122 q_entry = q_entry->next; 123 } 124 125 printf("\n"); 126 return 0; 127 }