Browse Source

getopt support

Suren A. Chilingaryan 12 years ago
parent
commit
1f4fe6e731
1 changed files with 222 additions and 36 deletions
  1. 222 36
      fwbench.c

+ 222 - 36
fwbench.c

@@ -9,6 +9,8 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <getopt.h>
+#include <stdarg.h>
 
 #include <fastwriter.h>
 
@@ -19,11 +21,9 @@
 #include "config.h"
 
 //#define USE_FIFO
-#define FW_BUFFER 4096l
 #define WRITE_INTERVAL 1
 #define WRITE_SUMMARY 5
 #define DELTA_TOLERANCE 5
-#define NEWFILE 10
 
 #ifdef USE_UFO_GENERATOR
 # ifndef USE_FIFO
@@ -31,7 +31,6 @@
 # endif /* !USE_FIFO */
 #endif /* USE_UFO_GENERATOR */
 
-#define run_time 3600
 const char *fifo_name = ".fifo";
 
 struct setup_s {
@@ -40,7 +39,13 @@ struct setup_s {
     size_t bpp;
     size_t fps;
 
+    size_t fpf;
     size_t iters;
+    double tolerance;
+    const char *output;
+    const char *fs;
+    
+    int verbose;
 
     volatile int run_started;
 
@@ -58,11 +63,64 @@ struct setup_s {
     size_t writeouts;
     
     fastwriter_t *fw;
+    char *current_output;
 };
 
 typedef struct setup_s setup_t;
 
 
+
+typedef enum {
+    OPT_OUTPUT = 'o',
+    OPT_BUFFER = 'b',
+    OPT_SIZE = 's',
+    OPT_TIME = 't',
+    OPT_RATE = 'r',
+    OPT_FRAMES = 'n',
+    OPT_GEOMETRY = 'g',
+    OPT_FPF = 'f',
+    OPT_MISSING = 'm',
+    OPT_QUIET = 'q',
+    OPT_HELP = 'h'
+} options_t;
+
+
+void Usage(int argc,  char* const argv[], const char *format, ...) {
+    if (format) {
+	va_list ap;
+    
+	va_start(ap, format);
+	printf("Error %i: ", errno);
+	vprintf(format, ap);
+	printf("\n");
+	va_end(ap);
+    
+        printf("\n");
+    }
+
+    printf(
+"Usage:\n"
+" %s [options]\n"
+"   -o <file|device>	- Output to file/device [/dev/null]\n"
+"			use %%zu to replace with frame number\n"
+"   -f <number>		- Number of frames per file [all]\n"
+"   -b size		- Buffer Size (MB)\n"
+"   -r rate		- Write rate (MB/s)\n"
+"   -s size		- Total size of data to write (GB)\n"
+"   -t run_time		- Run time (s)\n"
+"   -n frames		- Number of frames to write\n"
+"   -g <width>x<height>	- Geometry [1024]\n"
+"   -g <pixels>		- Number of megapixels [0.7]\n"
+"   -m <percent>	- Tolerable missing frames  [100%%]\n"
+"   -q			- Quiete\n"
+"   -h			- Help\n"
+"\n\n",
+argv[0]);
+
+    exit(0);
+}
+
+
 #ifdef USE_UFO_GENERATOR
 static void handle_error(GError *error) {
     if (error != NULL) {
@@ -73,6 +131,21 @@ static void handle_error(GError *error) {
 }
 #endif /* USE_UFO_GENERATOR */
 
+static void set_verbosity(setup_t *setup, int level) {
+    setup->verbose = level;
+}
+
+static void set_current_output(setup_t *setup, size_t frame) {
+    sprintf(setup->current_output, setup->output, frame);
+}
+
+static void set_output(setup_t *setup, const char *name) {
+    setup->output = name;
+    setup->fs = name;
+    setup->current_output = malloc(strlen(setup->output) + 32);
+    g_assert(setup->current_output);
+    set_current_output(setup, 0);
+}
 
 static void set_dim(setup_t *setup, size_t width, size_t height) {
     setup->bpp = sizeof(float);
@@ -82,18 +155,36 @@ static void set_dim(setup_t *setup, size_t width, size_t height) {
     setup->frame_size = setup->width * setup->height * setup->bpp;
 }
 
+static void set_pixels(setup_t *setup, size_t pixels) {
+    int width = sqrt(4 * pixels / 3);
+    set_dim(setup, width, width * 3 / 4);
+}
+
 static void set_speed(setup_t *setup, size_t speed) {
     setup->fps = 1 + speed / setup->width / setup->height / setup->bpp;
 }
 
+static void set_iters(setup_t *setup, size_t iters) {
+    setup->iters = iters;
+}
+
+static void set_time(setup_t *setup, size_t run_time) {
+    setup->iters = run_time * setup->fps;
+}
+
 static void set_size(setup_t *setup, size_t size) {
-    setup->iters = size / setup->width / setup->height / setup->bpp;
+    setup->iters = size / setup->frame_size + (size % setup->frame_size)?1:0;
+}
+
+static void set_frames_per_file(setup_t *setup, size_t fpf) {
+    setup->fpf = fpf;
 }
 
-static void set_time(setup_t *setup, size_t time) {
-    setup->iters = time * setup->fps;
+static void set_fail_tolerance(setup_t *setup, double fail_rate) {
+    setup->tolerance = fail_rate;
 }
 
+
 static int callback(setup_t *s, size_t result, void *buffer);
 
 static void *run(setup_t *setup) {
@@ -133,6 +224,8 @@ static void *run(setup_t *setup) {
 
     ufo_graph_run(graph, &error);
     handle_error(error);
+
+    g_thread_exit(NULL);
 #else /* USE_UFO_GENERATOR */
     size_t i;
     struct timeval tv;
@@ -148,7 +241,6 @@ static void *run(setup_t *setup) {
     int fd = open(fifo_name, O_WRONLY);
     g_assert(fd >= 0);
 #endif /* USE_FIFO */
-
     gettimeofday(&tv, NULL); 
     nexts = tv.tv_sec;
     nextus = tv.tv_usec + interval;
@@ -177,7 +269,6 @@ static void *run(setup_t *setup) {
 
 #endif /* USE_UFO_GENERATOR */
 
-    g_thread_exit(NULL);
     return NULL;
 }
 
@@ -191,11 +282,17 @@ static int callback(setup_t *s, size_t result, void *buffer) {
     size_t duration, last_duration, expected;
     long delta;
 
+    gettimeofday(&tv, NULL);
 
     if (!s->broken_frame) {
 	err = fastwriter_push(fw, result, buffer);
     	if (err) {
     	    if (err == EWOULDBLOCK) {
+    		if (!s->tolerance) {
+    		    if (s->verbose >= 0) printf("Lost frame...\n");
+    		    exit(1);
+    		}
+    		
 		if (s->num_read) fastwriter_cancel(fw);
 		s->broken_frame = 1;
     	    } else {
@@ -217,9 +314,21 @@ static int callback(setup_t *s, size_t result, void *buffer) {
     } else {
 	err = fastwriter_commit(fw);
 	s->frames++;
+
+	if ((s->fpf)&&((s->frames%s->fpf) == 0)) {
+	    fastwriter_close(s->fw);
+	    set_current_output(s, s->frames);
+	    err = fastwriter_open(s->fw, s->current_output,  FASTWRITER_FLAGS_OVERWRITE);
+	    if (err) {
+		printf("FastWriter returned error %i\n", err);
+		g_assert(!err);
+	    }
+
+	// reopen
     }
 
-    gettimeofday(&tv, NULL);
+    }
+    
     if (!s->tv_started.tv_sec) {
     	memcpy(&s->tv_started, &tv, sizeof(struct timeval));
     	if (s->tv_started.tv_usec >= (1000000 / s->fps)) 
@@ -235,9 +344,20 @@ static int callback(setup_t *s, size_t result, void *buffer) {
     if (stats.buffer_used > s->buf_max) s->buf_max = stats.buffer_used;
 
     if ((tv.tv_sec - s->tv_last_written.tv_sec) >= WRITE_INTERVAL) {
-	last_duration = (tv.tv_sec - s->tv_last_written.tv_sec) * 1000000 + (tv.tv_usec - s->tv_last_written.tv_usec);
-
-	printf("Lost  %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100.*(s->lost - s->last_lost) / (s->lost + s->frames - s->last_lost - s->last_frames), s->lost - s->last_lost, s->lost + s->frames - (s->last_lost + s->last_frames), 1. * s->frame_size * (s->frames - s->last_frames) / 1024 / 1024 / 1024, 1000000. * s->frame_size * (s->frames - s->last_frames) / last_duration / 1024 / 1024, 100.*s->buf_max/stats.buffer_size);
+	if ((s->tolerance > 0)&&(s->tolerance < 100)) {
+	    double lost = (100. * s->lost / (s->lost + s->frames));
+	    double last_lost = (100. * (s->lost - s->last_lost) / (s->lost + s->frames - s->last_lost - s->last_frames));
+	    if ((lost > s->tolerance)||(last_lost > s->tolerance)) {
+		if (s->verbose >= 0)
+		    printf("Lost %.2lf%% (%lu) frames, total: %.2lf%% (%lu)\n", last_lost, s->lost - s->last_lost, lost, s->lost);
+		exit(1);
+	    }
+	}
+	
+	if (s->verbose >= 0) {
+	    last_duration = (tv.tv_sec - s->tv_last_written.tv_sec) * 1000000 + (tv.tv_usec - s->tv_last_written.tv_usec);
+	    printf("Lost  %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100.*(s->lost - s->last_lost) / (s->lost + s->frames - s->last_lost - s->last_frames), s->lost - s->last_lost, s->lost + s->frames - (s->last_lost + s->last_frames), 1. * s->frame_size * (s->frames - s->last_frames) / 1024 / 1024 / 1024, 1000000. * s->frame_size * (s->frames - s->last_frames) / last_duration / 1024 / 1024, 100.*s->buf_max/stats.buffer_size);
+	}
 
 	if (((++s->writeouts)%WRITE_SUMMARY)==0) {
 	    duration = (tv.tv_sec - s->tv_started.tv_sec) * 1000000 + (tv.tv_usec - s->tv_started.tv_usec);
@@ -246,7 +366,9 @@ static int callback(setup_t *s, size_t result, void *buffer) {
     	    if ((delta > DELTA_TOLERANCE)||(delta < -DELTA_TOLERANCE))
     		printf(" *** Unexpected frame rate: %.2lf (%lu), delta: %li (%lu, %lu)\n", 1000000. * (s->frames + s->lost) / duration, s->fps, delta, s->lost + s->frames, expected); 
     		
-	    printf("Total %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100. * s->lost / (s->lost + s->frames), s->lost, s->lost + s->frames, 1. * s->frames * s->frame_size / 1024 / 1024 / 1024, 1000000. * s->frames * s->frame_size / duration / 1024 / 1024,  100.*stats.buffer_max / stats.buffer_size);
+    	    if (s->verbose >= 0) {
+		printf("Total %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100. * s->lost / (s->lost + s->frames), s->lost, s->lost + s->frames, 1. * s->frames * s->frame_size / 1024 / 1024 / 1024, 1000000. * s->frames * s->frame_size / duration / 1024 / 1024,  100.*stats.buffer_max / stats.buffer_size);
+	    }
 	}
 	
 	s->buf_max = 0;
@@ -259,7 +381,7 @@ static int callback(setup_t *s, size_t result, void *buffer) {
 }
 
 
-int main(int argc, char const* argv[])
+int main(int argc, char* const argv[])
 {
     int err;
 
@@ -269,12 +391,23 @@ int main(int argc, char const* argv[])
 #endif /* USE_FIFO */
 
     setup_t setup;
+
+    unsigned char c;
+    const char *sptr;
     const char *out = "/dev/null";
+    double mpix = 0;
     size_t width = 1024;
     size_t height = 768;
     size_t speed = 850;
+    size_t size = 0;
+    size_t run_time = 0;
+    size_t iters = 0x7FFFFFFF;
+    size_t fw_buffer = 0;
+    double fail_rate = 100.;
+    size_t fpf = 0;
+    int quiet = 0;
+    
 
-    fastwriter_t *fw;
     fastwriter_stats_t stats;
 
     g_thread_init(NULL);
@@ -283,12 +416,49 @@ int main(int argc, char const* argv[])
     g_type_init();
 #endif /* USE_UFO_GENERATOR */
 
-    if (argc > 1) {
-	out = argv[1];
-    }
-    
-    if (argc > 2) {
-	speed = atoi(argv[2]);
+
+
+    while ((c = getopt(argc, argv, "hqo:s:t:r:n:g:f:m:b:")) != (unsigned char)-1) {
+	switch (c) {
+	 case OPT_OUTPUT:
+	    out = optarg;
+	    break;
+	 case OPT_BUFFER:
+            fw_buffer = atol(optarg);
+	    break;
+         case OPT_SIZE:
+            size = atol(optarg);
+	    break;
+         case OPT_TIME:
+            run_time = atol(optarg);
+	    break;
+         case OPT_FRAMES:
+            iters = atol(optarg);
+	    break;
+         case OPT_RATE:
+            speed = atoi(optarg);
+            break;
+         case OPT_GEOMETRY:
+            sptr = strchr(optarg, 'x');
+            if (sptr) {
+        	width = atol(optarg);
+        	height = atol(sptr + 1);
+            } else {
+        	mpix = atof(optarg);
+            }
+            break;
+         case OPT_FPF:
+            fpf = atol(optarg);
+            break;
+         case OPT_MISSING:
+            fail_rate = atof(optarg);
+            break;
+        case OPT_QUIET:
+    	    quiet = 1;
+	    break;
+         case OPT_HELP:
+	    Usage(argc, argv, NULL);
+     }
     }
 
 #ifdef USE_FIFO
@@ -296,25 +466,41 @@ int main(int argc, char const* argv[])
     g_assert(!mkfifo(fifo_name, S_IWUSR | S_IRUSR));
 #endif /* USE_FIFO */
 
-    fw = fastwriter_init(out, FASTWRITER_FLAGS_OVERWRITE);
-    g_assert(fw);
+
+    memset(&setup, 0, sizeof(setup_t));
+
+    if (quiet) set_verbosity(&setup, -1);
+    set_output(&setup, out);
     
-    err = fastwriter_open(fw, out,  FASTWRITER_FLAGS_OVERWRITE);
-    if (err) printf("FastWriter returned error %i\n", err);
-    g_assert(!err);
+    if (mpix) set_pixels(&setup, mpix * 1000000);
+    else set_dim(&setup, width, height);
+
+    set_speed(&setup, speed * 1024 * 1024);
 
-    fastwriter_set_buffer_size(fw, FW_BUFFER * 1024 * 1024);
+    if (size) set_size(&setup, size * 1024 * 1024 * 1024);
+    else if (run_time) set_time(&setup, run_time);
+    else set_iters(&setup, iters);
     
-    fastwriter_get_stats(fw, &stats);
+    set_fail_tolerance(&setup, fail_rate);
+    set_frames_per_file(&setup, fpf);
 
-    memset(&setup, 0, sizeof(setup_t));
 
-    setup.fw = fw;
-    set_dim(&setup, width, height);
-    set_speed(&setup, speed * 1024 * 1024);
-    set_size(&setup, run_time * speed * 1024 * 1024);
+    setup.fw = fastwriter_init(setup.fs, FASTWRITER_FLAGS_OVERWRITE);
+    g_assert(setup.fw);
+
+    if (fw_buffer) 
+	fastwriter_set_buffer_size(setup.fw, fw_buffer * 1024 * 1024);
+    else
+	fastwriter_set_buffer_size(setup.fw, FASTWRITER_BUFFER_MAX);
+    
+    err = fastwriter_open(setup.fw, setup.current_output,  FASTWRITER_FLAGS_OVERWRITE);
+    if (err) printf("FastWriter returned error %i\n", err);
+    g_assert(!err);
+
 
-    printf("*** Writing to %s, rate: %lu, data: %lu MB/s, buffer: %lu MB\n", out, setup.fps, speed, stats.buffer_size);
+    fastwriter_get_stats(setup.fw, &stats);
+    if (!quiet)
+	printf("*** Writing to %s, rate: %lu, data: %lu MB/s, buffer: %lu MB\n", out, setup.fps, speed, stats.buffer_size/1024/1024);
 
     void *buffer = malloc(setup.frame_size);
     g_assert(buffer);
@@ -345,8 +531,8 @@ int main(int argc, char const* argv[])
 #endif /* USE_FIFO */
 
     free(buffer);
-    fastwriter_close(fw);
-    fastwriter_destroy(fw);
+    fastwriter_close(setup.fw);
+    fastwriter_destroy(setup.fw);
 
 #ifdef USE_FIFO
     unlink(fifo_name);