2 * Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
12 /*_************************************
14 **************************************/
15 #include "util.h" /* Compiler options, UTIL_GetFileSize */
16 #include <stdlib.h> /* malloc */
17 #include <stdio.h> /* fprintf, fopen, ftello64 */
18 #include <assert.h> /* assert */
20 #include "mem.h" /* U32 */
21 #ifndef ZSTD_DLL_IMPORT
22 #include "zstd_internal.h" /* ZSTD_blockHeaderSize, blockType_e, KB, MB */
27 typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
29 #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */
30 #include "zstd.h" /* ZSTD_versionString */
31 #include "util.h" /* time functions */
33 #include "bench.h" /* CustomBench*/
36 /*_************************************
38 **************************************/
39 #define PROGRAM_DESCRIPTION "Zstandard speed analyzer"
40 #define AUTHOR "Yann Collet"
41 #define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_versionString(), (int)(sizeof(void*)*8), AUTHOR, __DATE__
46 #define KNUTH 2654435761U
47 #define MAX_MEM (1984 MB)
49 #define DEFAULT_CLEVEL 1
51 #define COMPRESSIBILITY_DEFAULT 0.50
52 static const size_t g_sampleSize = 10000000;
54 #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */
57 /*_************************************
59 **************************************/
60 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
63 /*_************************************
64 * Benchmark Parameters
65 **************************************/
66 static U32 g_nbIterations = NBLOOPS;
67 static double g_compressibility = COMPRESSIBILITY_DEFAULT;
69 static void BMK_SetNbIterations(U32 nbLoops)
71 g_nbIterations = nbLoops;
72 DISPLAY("- %i iterations -\n", g_nbIterations);
76 /*_*******************************************************
78 *********************************************************/
79 static size_t BMK_findMaxMem(U64 requiredMem)
81 size_t const step = 64 MB;
84 requiredMem = (((requiredMem >> 26) + 1) << 26);
85 if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;
89 testmem = malloc ((size_t)requiredMem);
94 return (size_t) requiredMem;
98 /*_*******************************************************
100 *********************************************************/
102 static ZSTD_CCtx* g_zcc = NULL;
105 local_ZSTD_compress(const void* src, size_t srcSize,
106 void* dst, size_t dstSize,
110 ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };
112 p.cParams = *(ZSTD_compressionParameters*)buff2;
113 return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p);
114 //return ZSTD_compress(dst, dstSize, src, srcSize, cLevel);
117 static size_t g_cSize = 0;
118 static size_t local_ZSTD_decompress(const void* src, size_t srcSize,
119 void* dst, size_t dstSize,
122 (void)src; (void)srcSize;
123 return ZSTD_decompress(dst, dstSize, buff2, g_cSize);
126 static ZSTD_DCtx* g_zdc = NULL;
128 #ifndef ZSTD_DLL_IMPORT
129 extern size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* ctx, const void* src, size_t srcSize);
130 static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
132 (void)src; (void)srcSize; (void)dst; (void)dstSize;
133 return ZSTD_decodeLiteralsBlock((ZSTD_DCtx*)g_zdc, buff2, g_cSize);
136 extern size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeq, const void* src, size_t srcSize);
137 static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2)
140 (void)src; (void)srcSize; (void)dst; (void)dstSize;
141 return ZSTD_decodeSeqHeaders(g_zdc, &nbSeq, buff2, g_cSize);
145 static ZSTD_CStream* g_cstream= NULL;
147 local_ZSTD_compressStream(const void* src, size_t srcSize,
148 void* dst, size_t dstCapacity,
151 ZSTD_outBuffer buffOut;
152 ZSTD_inBuffer buffIn;
154 ZSTD_frameParameters f = {1 /* contentSizeHeader*/, 0, 0};
156 p.cParams = *(ZSTD_compressionParameters*)buff2;
157 ZSTD_initCStream_advanced(g_cstream, NULL, 0, p, ZSTD_CONTENTSIZE_UNKNOWN);
159 buffOut.size = dstCapacity;
162 buffIn.size = srcSize;
164 ZSTD_compressStream(g_cstream, &buffOut, &buffIn);
165 ZSTD_endStream(g_cstream, &buffOut);
170 local_ZSTD_compress_generic_end(const void* src, size_t srcSize,
171 void* dst, size_t dstCapacity,
174 ZSTD_outBuffer buffOut;
175 ZSTD_inBuffer buffIn;
178 buffOut.size = dstCapacity;
181 buffIn.size = srcSize;
183 ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end);
188 local_ZSTD_compress_generic_continue(const void* src, size_t srcSize,
189 void* dst, size_t dstCapacity,
192 ZSTD_outBuffer buffOut;
193 ZSTD_inBuffer buffIn;
196 buffOut.size = dstCapacity;
199 buffIn.size = srcSize;
201 ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);
202 ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end);
207 local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize,
208 void* dst, size_t dstCapacity,
211 ZSTD_outBuffer buffOut;
212 ZSTD_inBuffer buffIn;
214 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_nbWorkers, 2);
216 buffOut.size = dstCapacity;
219 buffIn.size = srcSize;
221 while (ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {}
226 local_ZSTD_compress_generic_T2_continue(const void* src, size_t srcSize,
227 void* dst, size_t dstCapacity,
230 ZSTD_outBuffer buffOut;
231 ZSTD_inBuffer buffIn;
233 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_nbWorkers, 2);
235 buffOut.size = dstCapacity;
238 buffIn.size = srcSize;
240 ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_continue);
241 while(ZSTD_compress_generic(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {}
245 static ZSTD_DStream* g_dstream= NULL;
247 local_ZSTD_decompressStream(const void* src, size_t srcSize,
248 void* dst, size_t dstCapacity,
251 ZSTD_outBuffer buffOut;
252 ZSTD_inBuffer buffIn;
253 (void)src; (void)srcSize;
254 ZSTD_initDStream(g_dstream);
256 buffOut.size = dstCapacity;
259 buffIn.size = g_cSize;
261 ZSTD_decompressStream(g_dstream, &buffOut, &buffIn);
265 #ifndef ZSTD_DLL_IMPORT
266 static size_t local_ZSTD_compressContinue(const void* src, size_t srcSize,
267 void* dst, size_t dstCapacity,
271 ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 };
273 p.cParams = *(ZSTD_compressionParameters*)buff2;
274 ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);
275 return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize);
278 #define FIRST_BLOCK_SIZE 8
279 static size_t local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize,
280 void* dst, size_t dstCapacity,
283 BYTE firstBlockBuf[FIRST_BLOCK_SIZE];
286 ZSTD_frameParameters f = { 1, 0, 0 };
288 p.cParams = *(ZSTD_compressionParameters*)buff2;
289 ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize);
290 memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE);
292 { size_t const compressResult = ZSTD_compressContinue(g_zcc,
294 firstBlockBuf, FIRST_BLOCK_SIZE);
295 if (ZSTD_isError(compressResult)) {
296 DISPLAY("local_ZSTD_compressContinue_extDict error : %s\n",
297 ZSTD_getErrorName(compressResult));
298 return compressResult;
300 dst = (BYTE*)dst + compressResult;
301 dstCapacity -= compressResult;
303 return ZSTD_compressEnd(g_zcc, dst, dstCapacity,
304 (const BYTE*)src + FIRST_BLOCK_SIZE,
305 srcSize - FIRST_BLOCK_SIZE);
308 static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize,
309 void* dst, size_t dstCapacity,
312 size_t regeneratedSize = 0;
313 const BYTE* ip = (const BYTE*)buff2;
314 const BYTE* const iend = ip + g_cSize;
315 BYTE* op = (BYTE*)dst;
316 size_t remainingCapacity = dstCapacity;
318 (void)src; (void)srcSize; /* unused */
319 ZSTD_decompressBegin(g_zdc);
321 size_t const iSize = ZSTD_nextSrcSizeToDecompress(g_zdc);
322 size_t const decodedSize = ZSTD_decompressContinue(g_zdc, op, remainingCapacity, ip, iSize);
324 regeneratedSize += decodedSize;
326 remainingCapacity -= decodedSize;
329 return regeneratedSize;
334 /*_*******************************************************
336 *********************************************************/
337 static size_t benchMem(U32 benchNb,
338 const void* src, size_t srcSize,
339 int cLevel, ZSTD_compressionParameters cparams)
341 size_t dstBuffSize = ZSTD_compressBound(srcSize);
345 const char* benchName;
346 BMK_benchFn_t benchFunction;
353 benchFunction = local_ZSTD_compress; benchName = "compress";
356 benchFunction = local_ZSTD_decompress; benchName = "decompress";
358 #ifndef ZSTD_DLL_IMPORT
360 benchFunction = local_ZSTD_compressContinue; benchName = "compressContinue";
363 benchFunction = local_ZSTD_compressContinue_extDict; benchName = "compressContinue_extDict";
366 benchFunction = local_ZSTD_decompressContinue; benchName = "decompressContinue";
369 benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "decodeLiteralsBlock";
372 benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "decodeSeqHeaders";
376 benchFunction = local_ZSTD_compressStream; benchName = "compressStream";
379 benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream";
382 benchFunction = local_ZSTD_compress_generic_continue; benchName = "compress_generic, continue";
385 benchFunction = local_ZSTD_compress_generic_end; benchName = "compress_generic, end";
388 benchFunction = local_ZSTD_compress_generic_T2_continue; benchName = "compress_generic, -T2, continue";
391 benchFunction = local_ZSTD_compress_generic_T2_end; benchName = "compress_generic, -T2, end";
398 dstBuff = (BYTE*)malloc(dstBuffSize);
399 dstBuff2 = malloc(dstBuffSize);
400 if ((!dstBuff) || (!dstBuff2)) {
401 DISPLAY("\nError: not enough memory!\n");
402 free(dstBuff); free(dstBuff2);
406 if (g_zcc==NULL) g_zcc = ZSTD_createCCtx();
407 if (g_zdc==NULL) g_zdc = ZSTD_createDCtx();
408 if (g_cstream==NULL) g_cstream = ZSTD_createCStream();
409 if (g_dstream==NULL) g_dstream = ZSTD_createDStream();
411 /* DISPLAY("params: cLevel %d, wlog %d hlog %d clog %d slog %d slen %d tlen %d strat %d \n",
412 cLevel, cparams->windowLog, cparams->hashLog, cparams->chainLog, cparams->searchLog,
413 cparams->searchLength, cparams->targetLength, cparams->strategy); */
415 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_compressionLevel, cLevel);
416 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_windowLog, cparams.windowLog);
417 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_hashLog, cparams.hashLog);
418 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_chainLog, cparams.chainLog);
419 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_searchLog, cparams.searchLog);
420 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_minMatch, cparams.searchLength);
421 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_targetLength, cparams.targetLength);
422 ZSTD_CCtx_setParameter(g_zcc, ZSTD_p_compressionStrategy, cparams.strategy);
425 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionLevel, cLevel);
426 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_windowLog, cparams.windowLog);
427 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_hashLog, cparams.hashLog);
428 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_chainLog, cparams.chainLog);
429 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_searchLog, cparams.searchLog);
430 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_minMatch, cparams.searchLength);
431 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_targetLength, cparams.targetLength);
432 ZSTD_CCtx_setParameter(g_cstream, ZSTD_p_compressionStrategy, cparams.strategy);
441 g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
443 #ifndef ZSTD_DLL_IMPORT
451 g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
453 case 31: /* ZSTD_decodeLiteralsBlock */
454 { blockProperties_t bp;
455 ZSTD_frameHeader zfp;
456 size_t frameHeaderSize, skippedSize;
457 g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel);
458 frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
459 if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min;
460 ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */
461 if (bp.blockType != bt_compressed) {
462 DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n");
465 skippedSize = frameHeaderSize + ZSTD_blockHeaderSize;
466 memcpy(buff2, dstBuff+skippedSize, g_cSize-skippedSize);
467 srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
468 ZSTD_decompressBegin(g_zdc);
471 case 32: /* ZSTD_decodeSeqHeaders */
472 { blockProperties_t bp;
473 ZSTD_frameHeader zfp;
474 const BYTE* ip = dstBuff;
476 size_t frameHeaderSize, cBlockSize;
477 ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); /* it would be better to use direct block compression here */
478 g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel);
479 frameHeaderSize = ZSTD_getFrameHeader(&zfp, dstBuff, ZSTD_frameHeaderSize_min);
480 if (frameHeaderSize==0) frameHeaderSize = ZSTD_frameHeaderSize_min;
481 ip += frameHeaderSize; /* Skip frame Header */
482 cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */
483 if (bp.blockType != bt_compressed) {
484 DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n");
487 iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */
488 ip += ZSTD_blockHeaderSize; /* skip block header */
489 ZSTD_decompressBegin(g_zdc);
490 ip += ZSTD_decodeLiteralsBlock(g_zdc, ip, iend-ip); /* skip literal segment */
492 memcpy(buff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */
493 srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */
504 g_cSize = ZSTD_compress(buff2, dstBuffSize, src, srcSize, cLevel);
508 /* convention: test functions have ID > 100 */
513 /* warming up dstBuff */
514 { size_t i; for (i=0; i<dstBuffSize; i++) dstBuff[i]=(BYTE)i; }
517 { BMK_timedFnState_t* const tfs = BMK_createTimedFnState(g_nbIterations * 1000, 1000);
518 BMK_runTime_t bestResult;
519 bestResult.sumOfReturn = 0;
520 bestResult.nanoSecPerRun = (unsigned long long)(-1LL);
523 void* const dstBuffv = dstBuff;
524 BMK_runOutcome_t const bOutcome =
525 BMK_benchTimedFn( tfs,
526 benchFunction, buff2,
527 NULL, NULL, /* initFn */
530 &dstBuffv, &dstBuffSize,
533 if (!BMK_isSuccessful_runOutcome(bOutcome)) {
534 DISPLAY("ERROR benchmarking function ! ! \n");
539 { BMK_runTime_t const newResult = BMK_extract_runTime(bOutcome);
540 if (newResult.nanoSecPerRun < bestResult.nanoSecPerRun )
541 bestResult.nanoSecPerRun = newResult.nanoSecPerRun;
542 DISPLAY("\r%2u#%-29.29s:%8.1f MB/s (%8u) ",
544 (double)srcSize * TIMELOOP_NANOSEC / bestResult.nanoSecPerRun / MB_UNIT,
545 (unsigned)newResult.sumOfReturn );
548 if ( BMK_isCompleted_TimedFn(tfs) ) break;
550 BMK_freeTimedFnState(tfs);
557 ZSTD_freeCCtx(g_zcc); g_zcc=NULL;
558 ZSTD_freeDCtx(g_zdc); g_zdc=NULL;
559 ZSTD_freeCStream(g_cstream); g_cstream=NULL;
560 ZSTD_freeDStream(g_dstream); g_dstream=NULL;
565 static int benchSample(U32 benchNb,
566 int cLevel, ZSTD_compressionParameters cparams)
568 size_t const benchedSize = g_sampleSize;
569 const char* const name = "Sample 10MiB";
572 void* const origBuff = malloc(benchedSize);
573 if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; }
576 RDG_genBuffer(origBuff, benchedSize, g_compressibility, 0.0, 0);
579 DISPLAY("\r%70s\r", "");
580 DISPLAY(" %s : \n", name);
582 benchMem(benchNb, origBuff, benchedSize, cLevel, cparams);
583 } else { /* 0 == run all tests */
584 for (benchNb=0; benchNb<100; benchNb++) {
585 benchMem(benchNb, origBuff, benchedSize, cLevel, cparams);
593 static int benchFiles(U32 benchNb,
594 const char** fileNamesTable, const int nbFiles,
595 int cLevel, ZSTD_compressionParameters cparams)
597 /* Loop for each file */
599 for (fileIdx=0; fileIdx<nbFiles; fileIdx++) {
600 const char* const inFileName = fileNamesTable[fileIdx];
601 FILE* const inFile = fopen( inFileName, "rb" );
604 /* Check file existence */
605 if (inFile==NULL) { DISPLAY( "Pb opening %s\n", inFileName); return 11; }
607 /* Memory allocation & restrictions */
608 { U64 const inFileSize = UTIL_getFileSize(inFileName);
609 if (inFileSize == UTIL_FILESIZE_UNKNOWN) {
610 DISPLAY( "Cannot measure size of %s\n", inFileName);
614 benchedSize = BMK_findMaxMem(inFileSize*3) / 3;
615 if ((U64)benchedSize > inFileSize)
616 benchedSize = (size_t)inFileSize;
617 if ((U64)benchedSize < inFileSize) {
618 DISPLAY("Not enough memory for '%s' full size; testing %u MB only... \n",
619 inFileName, (U32)(benchedSize>>20));
623 { void* const origBuff = malloc(benchedSize);
624 if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); fclose(inFile); return 12; }
626 /* Fill input buffer */
627 DISPLAY("Loading %s... \r", inFileName);
628 { size_t const readSize = fread(origBuff, 1, benchedSize, inFile);
630 if (readSize != benchedSize) {
631 DISPLAY("\nError: problem reading file '%s' !! \n", inFileName);
637 DISPLAY("\r%70s\r", ""); /* blank line */
638 DISPLAY(" %s : \n", inFileName);
640 benchMem(benchNb, origBuff, benchedSize, cLevel, cparams);
642 for (benchNb=0; benchNb<100; benchNb++) {
643 benchMem(benchNb, origBuff, benchedSize, cLevel, cparams);
654 /*_*******************************************************
656 *********************************************************/
658 #define ERROR_OUT(msg) { DISPLAY("%s \n", msg); exit(1); }
660 static unsigned readU32FromChar(const char** stringPtr)
662 const char errorMsg[] = "error: numeric value too large";
664 while ((**stringPtr >='0') && (**stringPtr <='9')) {
665 unsigned const max = (((unsigned)(-1)) / 10) - 1;
666 if (result > max) ERROR_OUT(errorMsg);
667 result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
669 if ((**stringPtr=='K') || (**stringPtr=='M')) {
670 unsigned const maxK = ((unsigned)(-1)) >> 10;
671 if (result > maxK) ERROR_OUT(errorMsg);
673 if (**stringPtr=='M') {
674 if (result > maxK) ERROR_OUT(errorMsg);
677 (*stringPtr)++; /* skip `K` or `M` */
678 if (**stringPtr=='i') (*stringPtr)++;
679 if (**stringPtr=='B') (*stringPtr)++;
684 static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
686 size_t const comSize = strlen(longCommand);
687 int const result = !strncmp(*stringPtr, longCommand, comSize);
688 if (result) *stringPtr += comSize;
693 /*_*******************************************************
695 *********************************************************/
697 static int usage(const char* exename)
699 DISPLAY( "Usage :\n");
700 DISPLAY( " %s [arg] file1 file2 ... fileX\n", exename);
701 DISPLAY( "Arguments :\n");
702 DISPLAY( " -H/-h : Help (this text + advanced options)\n");
706 static int usage_advanced(const char* exename)
709 DISPLAY( "\nAdvanced options :\n");
710 DISPLAY( " -b# : test only function # \n");
711 DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS);
712 DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100);
713 DISPLAY( " -l# : benchmark functions at that compression level (default : %i)\n", DEFAULT_CLEVEL);
714 DISPLAY( " --zstd : custom parameter selection. Format same as zstdcli \n");
718 static int badusage(const char* exename)
720 DISPLAY("Wrong parameters\n");
725 int main(int argc, const char** argv)
727 int argNb, filenamesStart=0, result;
728 const char* const exename = argv[0];
729 const char* input_filename = NULL;
730 U32 benchNb = 0, main_pause = 0;
731 int cLevel = DEFAULT_CLEVEL;
732 ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0);
734 DISPLAY(WELCOME_MESSAGE);
735 if (argc<1) return badusage(exename);
737 for (argNb=1; argNb<argc; argNb++) {
738 const char* argument = argv[argNb];
739 assert(argument != NULL);
741 if (longCommandWArg(&argument, "--zstd=")) {
743 if (longCommandWArg(&argument, "windowLog=") || longCommandWArg(&argument, "wlog=")) { cparams.windowLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
744 if (longCommandWArg(&argument, "chainLog=") || longCommandWArg(&argument, "clog=")) { cparams.chainLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
745 if (longCommandWArg(&argument, "hashLog=") || longCommandWArg(&argument, "hlog=")) { cparams.hashLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
746 if (longCommandWArg(&argument, "searchLog=") || longCommandWArg(&argument, "slog=")) { cparams.searchLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
747 if (longCommandWArg(&argument, "searchLength=") || longCommandWArg(&argument, "slen=")) { cparams.searchLength = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
748 if (longCommandWArg(&argument, "targetLength=") || longCommandWArg(&argument, "tlen=")) { cparams.targetLength = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; }
749 if (longCommandWArg(&argument, "strategy=") || longCommandWArg(&argument, "strat=")) { cparams.strategy = (ZSTD_strategy)(readU32FromChar(&argument)); if (argument[0]==',') { argument++; continue; } else break; }
750 if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevel = (int)readU32FromChar(&argument); cparams = ZSTD_getCParams(cLevel, 0, 0); if (argument[0]==',') { argument++; continue; } else break; }
751 DISPLAY("invalid compression parameter \n");
755 /* check end of string */
756 if (argument[0] != 0) {
757 DISPLAY("invalid --zstd= format \n");
763 } else if (argument[0]=='-') { /* Commands (note : aggregated commands are allowed) */
765 while (argument[0]!=0) {
769 /* Display help on usage */
771 case 'H': return usage_advanced(exename);
773 /* Pause at the end (hidden option) */
774 case 'p': main_pause = 1; break;
776 /* Select specific algorithm to bench */
779 benchNb = readU32FromChar(&argument);
782 /* Modify Nb Iterations */
785 BMK_SetNbIterations((int)readU32FromChar(&argument));
788 /* Select compressibility of synthetic sample */
791 g_compressibility = (double)readU32FromChar(&argument) / 100.;
795 cLevel = readU32FromChar(&argument);
796 cparams = ZSTD_getCParams(cLevel, 0, 0);
799 /* Unknown command */
800 default : return badusage(exename);
806 /* first provided filename is input */
807 if (!input_filename) { input_filename=argument; filenamesStart=argNb; continue; }
812 if (filenamesStart==0) /* no input file */
813 result = benchSample(benchNb, cLevel, cparams);
815 result = benchFiles(benchNb, argv+filenamesStart, argc-filenamesStart, cLevel, cparams);
817 if (main_pause) { int unused; printf("press enter...\n"); unused = getchar(); (void)unused; }