static void benchmark_codec (SquashCodec* codec, void* data) { struct BenchmarkContext* context = (struct BenchmarkContext*) data; SquashOptions* opts; int level = 0; char level_s[4]; bool have_results = false; umask (0100); fprintf (stdout, " %s:%s\n", squash_plugin_get_name (squash_codec_get_plugin (codec)), squash_codec_get_name (codec)); opts = squash_options_new (codec, NULL); if (opts != NULL) { squash_object_ref_sink (opts); for ( level = 0 ; level <= 999 ; level++ ) { snprintf (level_s, 4, "%d", level); if (squash_options_parse_option (opts, "level", level_s) == SQUASH_OK) { if (benchmark_codec_with_options (context, codec, opts)) { have_results = true; } } } squash_object_unref (opts); } if (!have_results) { benchmark_codec_with_options (context, codec, NULL); } }
static SquashCodec* benchmark_parse_codec (const char* str, SquashOptions** options) { SquashCodec* codec; char* s = strdup (str); char* sp_outer = NULL; char* sp_inner = NULL; char* cur_opt = NULL; char* cur_key = NULL; char* cur_val = NULL; SquashStatus res; char* name = strtok_r (s, "/", &sp_outer); codec = squash_get_codec (name); if (codec == NULL) return NULL; while ((cur_opt = strtok_r (NULL, ",", &sp_outer)) != NULL) { if (*options == NULL) { assert (codec != NULL); *options = squash_options_new (codec, NULL); squash_object_ref_sink (*options); } cur_key = strtok_r (cur_opt, "=", &sp_inner); cur_val = strtok_r (NULL, "=", &sp_inner); if (cur_val == NULL) { cur_val = cur_key; cur_key = "level"; } assert (*options != NULL); res = squash_options_parse_option (*options, cur_key, cur_val); if (res != SQUASH_OK) { fprintf (stderr, "Unable to parse options: %s (%d)\n", squash_status_to_string (res), res); exit (EXIT_FAILURE); } } free (s); return codec; }
int main(int argc, char *argv[]) { int ret; off_t size = 0, size_c = 0; size_t len, len_c; FILE *in; void *in_buf, *out_buf; uint64_t full_len, out_len; struct stat st; void *in_map = NULL; void *out_map = NULL; int out_fd; double time = 0.0; #ifdef USE_MMAP uint64_t out_mapped; #endif struct timespec start, stop, start_full, stop_full; if (argc < 4 || argc > 6) help(); if (argc == 5 || argc == 6) assert(*argv[1] == 's'); if (strlen(argv[1]) != 1) help(); //file handling in = fopen(argv[2], "r"); assert(in); out_fd = open(argv[3], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); assert(out_fd != -1); fstat(fileno(in), &st); full_len = st.st_size; #ifdef USE_MMAP switch(argv[1][0]) { case 'e' : out_mapped = full_len*2; break; case 'd' : out_mapped = CHUNK_SIZE*8; break; case 'm' : out_mapped = full_len; break; } #endif //initialisation #ifndef USE_MMAP_READ in_buf = malloc(CHUNK_SIZE); #else in_map = mmap(NULL, full_len, PROT_READ, MAP_SHARED, fileno(in), 0); if (in_map == MAP_FAILED) { printf("WARNING: mmap failed for %s, using regular write\n", argv[2]); in_map = NULL; in_buf = malloc(2*CHUNK_SIZE); } else in_buf = in_map; #endif #ifndef USE_MMAP_WRITE out_buf = malloc(2*CHUNK_SIZE); #else ftruncate(out_fd, out_mapped); out_map = mmap(NULL, out_mapped, PROT_WRITE, MAP_SHARED, out_fd, 0); if (out_map == MAP_FAILED) { printf("WARNING: mmap failed for %s, using regular write\n", argv[3]); out_map = NULL; out_buf = malloc(2*CHUNK_SIZE); } else out_buf = out_map; #endif switch(argv[1][0]) { #ifdef BBP_USE_SIMDCOMP case 'e' : clock_gettime(CLOCK_MONOTONIC, &start_full); #ifndef USE_MMAP_READ while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) { #else for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) { len = full_len - (in_buf-in_map); if (len > CHUNK_SIZE) len = CHUNK_SIZE; if (len % (128*4)) break; #endif int b; clock_gettime(CLOCK_MONOTONIC, &start); //compression for(b=0;b<BENCHMARK_ITERATIONS;b++) len_c = compress(in_buf, len/4, out_buf); clock_gettime(CLOCK_MONOTONIC, &stop); time += ms_delta(start, stop); size += len; size_c += len_c; if (!out_map) { len = write(out_fd, out_buf, len_c); assert(len == len_c); } else out_buf += len_c; } out_len = size_c; clock_gettime(CLOCK_MONOTONIC, &stop_full); printf("compressed at %.3f MB/s / %.3fMB/s ratio %.2f\n",(float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c); printf("%.2f %.3f simdcomp\n",(float)size/size_c, (float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time); break; #endif #ifdef BBP_USE_SQUASH case 's' : assert(argc == 5 || argc == 6); SquashCodec* codec = squash_get_codec(argv[4]); SquashOptions *options; assert(codec); if (argc == 6) { options = squash_options_new(codec, NULL); ret = squash_options_parse_option(options, "level", argv[5]); if (ret != SQUASH_OK) { if (ret == SQUASH_BAD_PARAM) printf("ERROR: SQUASH: bad param\n"); if (ret == SQUASH_BAD_VALUE) printf("ERROR: SQUASH: bad value\n"); break; } } else options = NULL; clock_gettime(CLOCK_MONOTONIC, &start_full); #ifndef USE_MMAP_READ while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) { #else for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) { len = full_len - (in_buf-in_map); if (len > CHUNK_SIZE) len = CHUNK_SIZE; #endif clock_gettime(CLOCK_MONOTONIC, &start); //compression len_c = 2*CHUNK_SIZE; if (options) squash_codec_compress_with_options(codec, &len_c, out_buf, len, in_buf, options); else ret = squash_compress(argv[4], &len_c, out_buf, len, in_buf, NULL); if (ret != SQUASH_OK) printf("ERROR: SQUASH (%s): %s\n",squash_status_to_string(ret), argv[4]); clock_gettime(CLOCK_MONOTONIC, &stop); time += ms_delta(start, stop); size += len; size_c += len_c; if (!out_map) { len = write(out_fd, out_buf, len_c); assert(len == len_c); } else out_buf += len_c; } out_len = size_c; clock_gettime(CLOCK_MONOTONIC, &stop_full); printf("compressed at %.3fMB/s / %.3fMB/s ratio %.2f\n",(float)size/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c); printf("%.2f %.3f %s\n",(float)size/size_c, (float)size/1024/1024*1000/time, argv[4]); break; #endif } if (in_map) munmap(in_map, full_len); fclose(in); if (out_map) munmap(out_map, full_len*2); ftruncate(out_fd, out_len); close(out_fd); return EXIT_SUCCESS; }