zstd/tests/paramgrill.c

1050 lines
38 KiB
C
Raw Normal View History

/*
* Copyright (c) 2015-present, Yann Collet, Facebook, Inc.
2016-08-30 10:04:33 -07:00
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
2016-08-30 10:04:33 -07:00
*/
2015-10-25 16:06:36 -07:00
2016-02-10 04:37:52 -08:00
/*-************************************
* Dependencies
2015-10-25 16:06:36 -07:00
**************************************/
#include "util.h" /* Compiler options, UTIL_GetFileSize */
#include <stdlib.h> /* malloc */
#include <stdio.h> /* fprintf, fopen, ftello64 */
#include <string.h> /* strcmp */
#include <math.h> /* log */
#include <time.h> /* clock_t */
2015-10-25 16:06:36 -07:00
#include "mem.h"
2016-07-10 18:12:17 -07:00
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_estimateCCtxSize */
#include "zstd.h"
2015-10-25 16:06:36 -07:00
#include "datagen.h"
#include "xxhash.h"
2016-02-10 04:37:52 -08:00
/*-************************************
2015-10-25 16:06:36 -07:00
* Constants
**************************************/
2016-04-28 05:40:45 -07:00
#define PROGRAM_DESCRIPTION "ZSTD parameters tester"
2015-10-25 16:06:36 -07:00
#define AUTHOR "Yann Collet"
#define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_VERSION_STRING, (int)(sizeof(void*)*8), AUTHOR, __DATE__
2015-10-25 16:06:36 -07:00
#define KB *(1<<10)
#define MB *(1<<20)
2015-11-27 08:52:57 -08:00
#define GB *(1ULL<<30)
2015-10-25 16:06:36 -07:00
2015-10-25 18:45:19 -07:00
#define NBLOOPS 2
2017-05-15 17:15:46 -07:00
#define TIMELOOP (2 * CLOCKS_PER_SEC)
2015-10-25 16:06:36 -07:00
2016-02-10 04:37:52 -08:00
#define NB_LEVELS_TRACKED 30
2015-11-27 08:52:57 -08:00
static const size_t maxMemory = (sizeof(size_t)==4) ? (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31));
2015-10-25 16:06:36 -07:00
#define COMPRESSIBILITY_DEFAULT 0.50
static const size_t sampleSize = 10000000;
2017-05-15 17:15:46 -07:00
static const double g_grillDuration_s = 90000; /* about 24 hours */
static const clock_t g_maxParamTime = 15 * CLOCKS_PER_SEC;
static const clock_t g_maxVariationTime = 60 * CLOCKS_PER_SEC;
2015-10-27 04:18:00 -07:00
static const int g_maxNbVariations = 64;
2015-10-25 16:06:36 -07:00
2015-11-27 08:46:14 -08:00
2016-02-10 04:37:52 -08:00
/*-************************************
2015-10-25 16:06:36 -07:00
* Macros
**************************************/
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#undef MIN
#undef MAX
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
2015-10-25 16:06:36 -07:00
2016-02-10 04:37:52 -08:00
/*-************************************
2015-10-25 16:06:36 -07:00
* Benchmark Parameters
**************************************/
2015-10-30 07:49:48 -07:00
static U32 g_nbIterations = NBLOOPS;
2015-10-25 16:06:36 -07:00
static double g_compressibility = COMPRESSIBILITY_DEFAULT;
static U32 g_blockSize = 0;
2015-10-26 07:45:58 -07:00
static U32 g_rand = 1;
2015-10-26 18:59:12 -07:00
static U32 g_singleRun = 0;
2015-10-27 04:18:00 -07:00
static U32 g_target = 0;
2015-10-27 05:12:25 -07:00
static U32 g_noSeed = 0;
2016-03-30 11:42:19 -07:00
static ZSTD_compressionParameters g_params = { 0, 0, 0, 0, 0, 0, ZSTD_greedy };
2015-10-25 16:06:36 -07:00
void BMK_SetNbIterations(int nbLoops)
{
2015-10-30 07:49:48 -07:00
g_nbIterations = nbLoops;
DISPLAY("- %u iterations -\n", g_nbIterations);
2015-10-25 16:06:36 -07:00
}
2016-02-10 04:37:52 -08:00
/*-*******************************************************
2015-10-25 16:06:36 -07:00
* Private functions
*********************************************************/
2017-05-15 17:15:46 -07:00
/* works even if overflow ; max span ~ 30 mn */
static clock_t BMK_clockSpan(clock_t cStart) { return clock() - cStart; }
2015-10-25 16:06:36 -07:00
2017-05-15 17:15:46 -07:00
/* accuracy in seconds only, span can be multiple years */
static double BMK_timeSpan(time_t tStart) { return difftime(time(NULL), tStart); }
2015-10-25 16:06:36 -07:00
static size_t BMK_findMaxMem(U64 requiredMem)
{
size_t const step = 64 MB;
void* testmem = NULL;
2015-10-25 16:06:36 -07:00
requiredMem = (((requiredMem >> 26) + 1) << 26);
2015-11-27 08:52:57 -08:00
if (requiredMem > maxMemory) requiredMem = maxMemory;
2015-10-25 16:06:36 -07:00
requiredMem += 2*step;
2016-02-10 04:37:52 -08:00
while (!testmem) {
2015-10-25 16:06:36 -07:00
requiredMem -= step;
testmem = malloc ((size_t)requiredMem);
2015-10-25 16:06:36 -07:00
}
free (testmem);
return (size_t) (requiredMem - step);
}
static U32 FUZ_rotl32(U32 x, U32 r)
{
return ((x << r) | (x >> (32 - r)));
}
2015-10-25 16:06:36 -07:00
U32 FUZ_rand(U32* src)
{
const U32 prime1 = 2654435761U;
const U32 prime2 = 2246822519U;
U32 rand32 = *src;
rand32 *= prime1;
rand32 += prime2;
rand32 = FUZ_rotl32(rand32, 13);
*src = rand32;
return rand32 >> 5;
}
2016-02-10 04:37:52 -08:00
/*-*******************************************************
2015-10-25 16:06:36 -07:00
* Bench functions
*********************************************************/
typedef struct {
size_t cSize;
double cSpeed; /* bytes / sec */
double dSpeed;
2015-10-25 16:06:36 -07:00
} BMK_result_t;
typedef struct
{
const char* srcPtr;
size_t srcSize;
char* cPtr;
size_t cRoom;
size_t cSize;
char* resPtr;
size_t resSize;
} blockParam_t;
static size_t BMK_benchParam(BMK_result_t* resultPtr,
const void* srcBuffer, size_t srcSize,
ZSTD_CCtx* ctx,
2016-03-30 11:42:19 -07:00
const ZSTD_compressionParameters cParams)
2015-10-25 16:06:36 -07:00
{
const size_t blockSize = g_blockSize ? g_blockSize : srcSize;
const U32 nbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize);
blockParam_t* const blockTable = (blockParam_t*) malloc(nbBlocks * sizeof(blockParam_t));
const size_t maxCompressedSize = (size_t)nbBlocks * ZSTD_compressBound(blockSize);
void* const compressedBuffer = malloc(maxCompressedSize);
void* const resultBuffer = malloc(srcSize);
2016-03-30 11:42:19 -07:00
ZSTD_parameters params;
U32 Wlog = cParams.windowLog;
2016-04-04 04:49:18 -07:00
U32 Clog = cParams.chainLog;
2016-03-30 11:42:19 -07:00
U32 Hlog = cParams.hashLog;
U32 Slog = cParams.searchLog;
U32 Slength = cParams.searchLength;
U32 Tlength = cParams.targetLength;
ZSTD_strategy strat = cParams.strategy;
2015-10-31 04:57:14 -07:00
char name[30] = { 0 };
2015-10-25 16:06:36 -07:00
U64 crcOrig;
/* init result for early exit */
resultPtr->cSize = srcSize;
resultPtr->cSpeed = 0.;
resultPtr->dSpeed = 0.;
2015-10-25 16:06:36 -07:00
/* Memory allocation & restrictions */
2016-02-10 04:37:52 -08:00
snprintf(name, 30, "Sw%02uc%02uh%02us%02ul%1ut%03uS%1u", Wlog, Clog, Hlog, Slog, Slength, Tlength, strat);
if (!compressedBuffer || !resultBuffer || !blockTable) {
2015-10-25 16:06:36 -07:00
DISPLAY("\nError: not enough memory!\n");
free(compressedBuffer);
free(resultBuffer);
free(blockTable);
return 12;
}
/* Calculating input Checksum */
crcOrig = XXH64(srcBuffer, srcSize, 0);
/* Init blockTable data */
{
U32 i;
size_t remaining = srcSize;
const char* srcPtr = (const char*)srcBuffer;
char* cPtr = (char*)compressedBuffer;
char* resPtr = (char*)resultBuffer;
2016-02-10 04:37:52 -08:00
for (i=0; i<nbBlocks; i++) {
2015-10-25 16:06:36 -07:00
size_t thisBlockSize = MIN(remaining, blockSize);
blockTable[i].srcPtr = srcPtr;
blockTable[i].cPtr = cPtr;
blockTable[i].resPtr = resPtr;
blockTable[i].srcSize = thisBlockSize;
blockTable[i].cRoom = ZSTD_compressBound(thisBlockSize);
srcPtr += thisBlockSize;
cPtr += blockTable[i].cRoom;
resPtr += thisBlockSize;
remaining -= thisBlockSize;
2016-02-10 04:37:52 -08:00
} }
2015-10-25 16:06:36 -07:00
/* warmimg up memory */
RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.10, 1);
/* Bench */
{ U32 loopNb;
2015-10-25 16:06:36 -07:00
size_t cSize = 0;
double fastestC = 100000000., fastestD = 100000000.;
double ratio = 0.;
2016-07-14 07:52:45 -07:00
clock_t const benchStart = clock();
2015-10-25 16:06:36 -07:00
DISPLAY("\r%79s\r", "");
2016-07-10 18:12:17 -07:00
memset(&params, 0, sizeof(params));
2016-03-30 11:42:19 -07:00
params.cParams = cParams;
2016-02-10 04:37:52 -08:00
for (loopNb = 1; loopNb <= g_nbIterations; loopNb++) {
2015-10-25 16:06:36 -07:00
int nbLoops;
U32 blockNb;
clock_t roundStart, roundClock;
2015-10-26 07:45:58 -07:00
{ clock_t const benchTime = BMK_clockSpan(benchStart);
if (benchTime > g_maxParamTime) break; }
2015-10-25 16:06:36 -07:00
/* Compression */
2015-11-04 03:05:27 -08:00
DISPLAY("\r%1u-%s : %9u ->", loopNb, name, (U32)srcSize);
2015-10-25 16:06:36 -07:00
memset(compressedBuffer, 0xE5, maxCompressedSize);
nbLoops = 0;
roundStart = clock();
while (clock() == roundStart);
roundStart = clock();
while (BMK_clockSpan(roundStart) < TIMELOOP) {
2015-10-25 16:06:36 -07:00
for (blockNb=0; blockNb<nbBlocks; blockNb++)
blockTable[blockNb].cSize = ZSTD_compress_advanced(ctx,
2015-10-26 07:45:58 -07:00
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
blockTable[blockNb].srcPtr, blockTable[blockNb].srcSize,
2015-12-17 16:26:48 -08:00
NULL, 0,
2015-10-26 07:45:58 -07:00
params);
2015-10-25 16:06:36 -07:00
nbLoops++;
}
roundClock = BMK_clockSpan(roundStart);
2015-10-25 16:06:36 -07:00
cSize = 0;
for (blockNb=0; blockNb<nbBlocks; blockNb++)
cSize += blockTable[blockNb].cSize;
ratio = (double)srcSize / (double)cSize;
if ((double)roundClock < fastestC * CLOCKS_PER_SEC * nbLoops) fastestC = ((double)roundClock / CLOCKS_PER_SEC) / nbLoops;
2015-11-04 03:05:27 -08:00
DISPLAY("\r");
2015-10-31 04:57:14 -07:00
DISPLAY("%1u-%s : %9u ->", loopNb, name, (U32)srcSize);
DISPLAY(" %9u (%4.3f),%7.1f MB/s", (U32)cSize, ratio, (double)srcSize / fastestC / 1000000.);
2015-10-25 16:06:36 -07:00
resultPtr->cSize = cSize;
resultPtr->cSpeed = (double)srcSize / fastestC;
2015-10-25 16:06:36 -07:00
#if 1
/* Decompression */
memset(resultBuffer, 0xD6, srcSize);
nbLoops = 0;
roundStart = clock();
while (clock() == roundStart);
roundStart = clock();
for ( ; BMK_clockSpan(roundStart) < TIMELOOP; nbLoops++) {
2015-10-25 16:06:36 -07:00
for (blockNb=0; blockNb<nbBlocks; blockNb++)
blockTable[blockNb].resSize = ZSTD_decompress(blockTable[blockNb].resPtr, blockTable[blockNb].srcSize,
blockTable[blockNb].cPtr, blockTable[blockNb].cSize);
}
roundClock = BMK_clockSpan(roundStart);
2015-10-25 16:06:36 -07:00
if ((double)roundClock < fastestD * CLOCKS_PER_SEC * nbLoops) fastestD = ((double)roundClock / CLOCKS_PER_SEC) / nbLoops;
2015-11-04 03:05:27 -08:00
DISPLAY("\r");
2015-10-31 04:57:14 -07:00
DISPLAY("%1u-%s : %9u -> ", loopNb, name, (U32)srcSize);
DISPLAY("%9u (%4.3f),%7.1f MB/s, ", (U32)cSize, ratio, (double)srcSize / fastestC / 1000000.);
DISPLAY("%7.1f MB/s", (double)srcSize / fastestD / 1000000.);
resultPtr->dSpeed = (double)srcSize / fastestD;
2015-10-25 16:06:36 -07:00
/* CRC Checking */
{ U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
if (crcOrig!=crcCheck) {
unsigned u;
unsigned eBlockSize = (unsigned)(MIN(65536*2, blockSize));
DISPLAY("\n!!! WARNING !!! Invalid Checksum : %x != %x\n", (unsigned)crcOrig, (unsigned)crcCheck);
for (u=0; u<srcSize; u++) {
if (((const BYTE*)srcBuffer)[u] != ((BYTE*)resultBuffer)[u]) {
printf("Decoding error at pos %u (block %u, pos %u) \n", u, u / eBlockSize, u % eBlockSize);
break;
} }
break;
} }
2015-10-25 16:06:36 -07:00
#endif
2016-02-10 04:37:52 -08:00
} }
2015-10-25 16:06:36 -07:00
/* End cleaning */
2015-11-04 03:05:27 -08:00
DISPLAY("\r");
2015-10-25 16:06:36 -07:00
free(compressedBuffer);
free(resultBuffer);
return 0;
}
2015-11-04 03:05:27 -08:00
2017-03-09 11:44:25 -08:00
const char* g_stratName[] = { "ZSTD_fast ",
"ZSTD_dfast ",
"ZSTD_greedy ",
"ZSTD_lazy ",
"ZSTD_lazy2 ",
"ZSTD_btlazy2 ",
"ZSTD_btopt ",
"ZSTD_btultra "};
2015-10-25 16:06:36 -07:00
2016-03-30 11:42:19 -07:00
static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_compressionParameters params, size_t srcSize)
2015-10-25 16:06:36 -07:00
{
DISPLAY("\r%79s\r", "");
2016-03-30 11:42:19 -07:00
fprintf(f," {%3u,%3u,%3u,%3u,%3u,%3u, %s }, ",
2016-04-04 04:49:18 -07:00
params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength,
params.targetLength, g_stratName[(U32)(params.strategy)]);
2015-10-26 07:45:58 -07:00
fprintf(f,
2015-11-02 07:14:46 -08:00
"/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */\n",
cLevel, (double)srcSize / result.cSize, result.cSpeed / 1000000., result.dSpeed / 1000000.);
2015-10-25 16:06:36 -07:00
}
static double g_cSpeedTarget[NB_LEVELS_TRACKED] = { 0. }; /* NB_LEVELS_TRACKED : checked at main() */
2015-10-25 18:45:19 -07:00
2015-10-25 16:06:36 -07:00
typedef struct {
BMK_result_t result;
2016-03-30 11:42:19 -07:00
ZSTD_compressionParameters params;
2015-10-25 16:06:36 -07:00
} winnerInfo_t;
2015-10-26 18:59:12 -07:00
static void BMK_printWinners2(FILE* f, const winnerInfo_t* winners, size_t srcSize)
2015-10-25 16:06:36 -07:00
{
int cLevel;
2015-10-25 16:06:36 -07:00
2015-11-27 08:46:14 -08:00
fprintf(f, "\n /* Proposed configurations : */ \n");
2016-03-30 11:42:19 -07:00
fprintf(f, " /* W, C, H, S, L, T, strat */ \n");
2015-10-25 16:06:36 -07:00
2016-02-10 04:37:52 -08:00
for (cLevel=0; cLevel <= ZSTD_maxCLevel(); cLevel++)
2015-10-26 07:45:58 -07:00
BMK_printWinner(f, cLevel, winners[cLevel].result, winners[cLevel].params, srcSize);
2015-10-25 16:06:36 -07:00
}
2015-10-26 18:59:12 -07:00
static void BMK_printWinners(FILE* f, const winnerInfo_t* winners, size_t srcSize)
{
fseek(f, 0, SEEK_SET);
BMK_printWinners2(f, winners, srcSize);
2015-10-28 06:05:37 -07:00
fflush(f);
2015-10-26 18:59:12 -07:00
BMK_printWinners2(stdout, winners, srcSize);
}
2016-03-30 11:42:19 -07:00
static int BMK_seed(winnerInfo_t* winners, const ZSTD_compressionParameters params,
2015-10-26 07:45:58 -07:00
const void* srcBuffer, size_t srcSize,
ZSTD_CCtx* ctx)
2015-10-25 16:06:36 -07:00
{
BMK_result_t testResult;
int better = 0;
int cLevel;
2015-10-25 16:06:36 -07:00
BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, params);
2016-02-10 04:37:52 -08:00
for (cLevel = 1; cLevel <= ZSTD_maxCLevel(); cLevel++) {
2015-10-28 07:56:48 -07:00
if (testResult.cSpeed < g_cSpeedTarget[cLevel])
continue; /* not fast enough for this level */
2016-02-10 04:37:52 -08:00
if (winners[cLevel].result.cSize==0) {
2015-10-28 07:56:48 -07:00
/* first solution for this cLevel */
winners[cLevel].result = testResult;
winners[cLevel].params = params;
BMK_printWinner(stdout, cLevel, testResult, params, srcSize);
better = 1;
continue;
}
2015-10-28 04:32:25 -07:00
2016-02-10 04:37:52 -08:00
if ((double)testResult.cSize <= ((double)winners[cLevel].result.cSize * (1. + (0.02 / cLevel))) ) {
2015-10-28 04:32:25 -07:00
/* Validate solution is "good enough" */
2015-10-28 07:56:48 -07:00
double W_ratio = (double)srcSize / testResult.cSize;
double O_ratio = (double)srcSize / winners[cLevel].result.cSize;
double W_ratioNote = log (W_ratio);
double O_ratioNote = log (O_ratio);
2015-10-28 04:32:25 -07:00
size_t W_DMemUsed = (1 << params.windowLog) + (16 KB);
size_t O_DMemUsed = (1 << winners[cLevel].params.windowLog) + (16 KB);
2015-10-28 11:07:05 -07:00
double W_DMemUsed_note = W_ratioNote * ( 40 + 9*cLevel) - log((double)W_DMemUsed);
double O_DMemUsed_note = O_ratioNote * ( 40 + 9*cLevel) - log((double)O_DMemUsed);
2015-10-28 04:32:25 -07:00
size_t W_CMemUsed = (1 << params.windowLog) + ZSTD_estimateCCtxSize_usingCParams(params);
size_t O_CMemUsed = (1 << winners[cLevel].params.windowLog) + ZSTD_estimateCCtxSize_usingCParams(winners[cLevel].params);
2015-10-28 07:56:48 -07:00
double W_CMemUsed_note = W_ratioNote * ( 50 + 13*cLevel) - log((double)W_CMemUsed);
double O_CMemUsed_note = O_ratioNote * ( 50 + 13*cLevel) - log((double)O_CMemUsed);
2015-10-28 04:32:25 -07:00
double W_CSpeed_note = W_ratioNote * ( 30 + 10*cLevel) + log(testResult.cSpeed);
double O_CSpeed_note = O_ratioNote * ( 30 + 10*cLevel) + log(winners[cLevel].result.cSpeed);
2015-10-28 06:05:37 -07:00
double W_DSpeed_note = W_ratioNote * ( 20 + 2*cLevel) + log(testResult.dSpeed);
double O_DSpeed_note = O_ratioNote * ( 20 + 2*cLevel) + log(winners[cLevel].result.dSpeed);
2015-10-28 06:05:37 -07:00
2016-02-10 04:37:52 -08:00
if (W_DMemUsed_note < O_DMemUsed_note) {
2015-10-28 07:56:48 -07:00
/* uses too much Decompression memory for too little benefit */
if (W_ratio > O_ratio)
DISPLAY ("Decompression Memory : %5.3f @ %4.1f MB vs %5.3f @ %4.1f MB : not enough for level %i\n",
W_ratio, (double)(W_DMemUsed) / 1024 / 1024,
O_ratio, (double)(O_DMemUsed) / 1024 / 1024, cLevel);
continue;
}
2016-02-10 04:37:52 -08:00
if (W_CMemUsed_note < O_CMemUsed_note) {
2015-10-28 07:56:48 -07:00
/* uses too much memory for compression for too little benefit */
if (W_ratio > O_ratio)
DISPLAY ("Compression Memory : %5.3f @ %4.1f MB vs %5.3f @ %4.1f MB : not enough for level %i\n",
W_ratio, (double)(W_CMemUsed) / 1024 / 1024,
O_ratio, (double)(O_CMemUsed) / 1024 / 1024, cLevel);
continue;
}
2016-02-10 04:37:52 -08:00
if (W_CSpeed_note < O_CSpeed_note ) {
2015-10-28 07:56:48 -07:00
/* too large compression speed difference for the compression benefit */
if (W_ratio > O_ratio)
DISPLAY ("Compression Speed : %5.3f @ %4.1f MB/s vs %5.3f @ %4.1f MB/s : not enough for level %i\n",
W_ratio, testResult.cSpeed / 1000000,
O_ratio, winners[cLevel].result.cSpeed / 1000000., cLevel);
2015-10-28 07:56:48 -07:00
continue;
}
2016-02-10 04:37:52 -08:00
if (W_DSpeed_note < O_DSpeed_note ) {
2015-10-28 07:56:48 -07:00
/* too large decompression speed difference for the compression benefit */
if (W_ratio > O_ratio)
DISPLAY ("Decompression Speed : %5.3f @ %4.1f MB/s vs %5.3f @ %4.1f MB/s : not enough for level %i\n",
W_ratio, testResult.dSpeed / 1000000.,
O_ratio, winners[cLevel].result.dSpeed / 1000000., cLevel);
2015-10-28 07:56:48 -07:00
continue;
}
2015-10-28 04:32:25 -07:00
2015-10-28 07:56:48 -07:00
if (W_ratio < O_ratio)
DISPLAY("Solution %4.3f selected over %4.3f at level %i, due to better secondary statistics \n", W_ratio, O_ratio, cLevel);
2015-10-28 04:32:25 -07:00
2015-10-25 16:06:36 -07:00
winners[cLevel].result = testResult;
winners[cLevel].params = params;
2015-10-26 07:45:58 -07:00
BMK_printWinner(stdout, cLevel, testResult, params, srcSize);
2015-10-28 07:56:48 -07:00
better = 1;
2016-02-10 04:37:52 -08:00
} }
2015-10-25 16:06:36 -07:00
2015-10-26 07:45:58 -07:00
return better;
}
2015-10-25 16:06:36 -07:00
2015-11-09 03:07:44 -08:00
/* nullified useless params, to ensure count stats */
2016-03-30 11:42:19 -07:00
static ZSTD_compressionParameters* sanitizeParams(ZSTD_compressionParameters params)
2015-11-09 03:07:44 -08:00
{
g_params = params;
if (params.strategy == ZSTD_fast)
2016-04-04 04:49:18 -07:00
g_params.chainLog = 0, g_params.searchLog = 0;
2016-07-13 02:49:05 -07:00
if (params.strategy == ZSTD_dfast)
g_params.searchLog = 0;
2017-03-09 11:44:25 -08:00
if (params.strategy != ZSTD_btopt && params.strategy != ZSTD_btultra)
g_params.targetLength = 0;
2015-11-09 03:07:44 -08:00
return &g_params;
}
2015-11-27 08:46:14 -08:00
2016-03-30 11:42:19 -07:00
static void paramVariation(ZSTD_compressionParameters* ptr)
2015-11-27 08:46:14 -08:00
{
2016-03-30 11:42:19 -07:00
ZSTD_compressionParameters p;
U32 validated = 0;
while (!validated) {
U32 nbChanges = (FUZ_rand(&g_rand) & 3) + 1;
p = *ptr;
for ( ; nbChanges ; nbChanges--) {
const U32 changeID = FUZ_rand(&g_rand) % 14;
switch(changeID)
{
case 0:
2016-04-04 04:49:18 -07:00
p.chainLog++; break;
2016-03-30 11:42:19 -07:00
case 1:
2016-04-04 04:49:18 -07:00
p.chainLog--; break;
2016-03-30 11:42:19 -07:00
case 2:
p.hashLog++; break;
case 3:
p.hashLog--; break;
case 4:
p.searchLog++; break;
case 5:
p.searchLog--; break;
case 6:
p.windowLog++; break;
case 7:
p.windowLog--; break;
case 8:
p.searchLength++; break;
case 9:
p.searchLength--; break;
case 10:
p.strategy = (ZSTD_strategy)(((U32)p.strategy)+1); break;
case 11:
p.strategy = (ZSTD_strategy)(((U32)p.strategy)-1); break;
case 12:
p.targetLength *= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
case 13:
p.targetLength /= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
}
2015-11-27 08:46:14 -08:00
}
2016-03-30 11:42:19 -07:00
validated = !ZSTD_isError(ZSTD_checkCParams(p));
2015-11-27 08:46:14 -08:00
}
2016-03-30 11:42:19 -07:00
*ptr = p;
2015-11-27 08:46:14 -08:00
}
2015-11-09 02:39:48 -08:00
#define PARAMTABLELOG 25
#define PARAMTABLESIZE (1<<PARAMTABLELOG)
#define PARAMTABLEMASK (PARAMTABLESIZE-1)
static BYTE g_alreadyTested[PARAMTABLESIZE] = {0}; /* init to zero */
2015-10-25 16:06:36 -07:00
2015-10-26 07:45:58 -07:00
#define NB_TESTS_PLAYED(p) \
2015-11-09 03:07:44 -08:00
g_alreadyTested[(XXH64(sanitizeParams(p), sizeof(p), 0) >> 3) & PARAMTABLEMASK]
2015-11-09 02:39:48 -08:00
2015-10-25 16:06:36 -07:00
2015-10-26 07:45:58 -07:00
static void playAround(FILE* f, winnerInfo_t* winners,
2016-03-30 11:42:19 -07:00
ZSTD_compressionParameters params,
2015-10-26 07:45:58 -07:00
const void* srcBuffer, size_t srcSize,
ZSTD_CCtx* ctx)
2015-10-26 07:45:58 -07:00
{
int nbVariations = 0;
clock_t const clockStart = clock();
2015-10-27 05:12:25 -07:00
while (BMK_clockSpan(clockStart) < g_maxVariationTime) {
2016-03-30 11:42:19 -07:00
ZSTD_compressionParameters p = params;
2015-10-25 16:06:36 -07:00
2015-11-27 08:46:14 -08:00
if (nbVariations++ > g_maxNbVariations) break;
paramVariation(&p);
2015-10-26 07:45:58 -07:00
/* exclude faster if already played params */
2015-11-01 05:32:59 -08:00
if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(p))-1))
continue;
2015-10-26 07:45:58 -07:00
/* test */
NB_TESTS_PLAYED(p)++;
if (!BMK_seed(winners, p, srcBuffer, srcSize, ctx)) continue;
/* improvement found => search more */
BMK_printWinners(f, winners, srcSize);
playAround(f, winners, p, srcBuffer, srcSize, ctx);
2015-10-25 16:06:36 -07:00
}
2015-10-26 07:45:58 -07:00
}
2016-06-01 09:59:55 -07:00
static ZSTD_compressionParameters randomParams(void)
2015-11-27 08:46:14 -08:00
{
2016-06-01 09:59:55 -07:00
ZSTD_compressionParameters p;
2016-03-30 11:42:19 -07:00
U32 validated = 0;
while (!validated) {
2015-11-27 08:46:14 -08:00
/* totally random entry */
2016-06-01 09:59:55 -07:00
p.chainLog = FUZ_rand(&g_rand) % (ZSTD_CHAINLOG_MAX+1 - ZSTD_CHAINLOG_MIN) + ZSTD_CHAINLOG_MIN;
p.hashLog = FUZ_rand(&g_rand) % (ZSTD_HASHLOG_MAX+1 - ZSTD_HASHLOG_MIN) + ZSTD_HASHLOG_MIN;
p.searchLog = FUZ_rand(&g_rand) % (ZSTD_SEARCHLOG_MAX+1 - ZSTD_SEARCHLOG_MIN) + ZSTD_SEARCHLOG_MIN;
p.windowLog = FUZ_rand(&g_rand) % (ZSTD_WINDOWLOG_MAX+1 - ZSTD_WINDOWLOG_MIN) + ZSTD_WINDOWLOG_MIN;
p.searchLength=FUZ_rand(&g_rand) % (ZSTD_SEARCHLENGTH_MAX+1 - ZSTD_SEARCHLENGTH_MIN) + ZSTD_SEARCHLENGTH_MIN;
p.targetLength=FUZ_rand(&g_rand) % (ZSTD_TARGETLENGTH_MAX+1 - ZSTD_TARGETLENGTH_MIN) + ZSTD_TARGETLENGTH_MIN;
2017-03-09 11:44:25 -08:00
p.strategy = (ZSTD_strategy) (FUZ_rand(&g_rand) % (ZSTD_btultra +1));
2016-06-01 09:59:55 -07:00
validated = !ZSTD_isError(ZSTD_checkCParams(p));
2015-11-27 08:46:14 -08:00
}
2016-06-01 09:59:55 -07:00
return p;
2015-11-27 08:46:14 -08:00
}
2015-10-26 07:45:58 -07:00
static void BMK_selectRandomStart(
FILE* f, winnerInfo_t* winners,
const void* srcBuffer, size_t srcSize,
ZSTD_CCtx* ctx)
2015-10-26 07:45:58 -07:00
{
2016-06-01 09:59:55 -07:00
U32 const id = (FUZ_rand(&g_rand) % (ZSTD_maxCLevel()+1));
2016-02-10 04:37:52 -08:00
if ((id==0) || (winners[id].params.windowLog==0)) {
2015-10-26 07:45:58 -07:00
/* totally random entry */
2016-06-01 09:59:55 -07:00
ZSTD_compressionParameters const p = ZSTD_adjustCParams(randomParams(), srcSize, 0);
2015-10-26 07:45:58 -07:00
playAround(f, winners, p, srcBuffer, srcSize, ctx);
2015-10-25 16:06:36 -07:00
}
2015-10-26 07:45:58 -07:00
else
playAround(f, winners, winners[id].params, srcBuffer, srcSize, ctx);
2015-10-25 16:06:36 -07:00
}
2015-10-26 07:45:58 -07:00
2015-10-25 16:06:36 -07:00
static void BMK_benchMem(void* srcBuffer, size_t srcSize)
{
2016-07-12 04:42:10 -07:00
ZSTD_CCtx* const ctx = ZSTD_createCCtx();
2016-03-30 11:42:19 -07:00
ZSTD_compressionParameters params;
2016-02-10 04:37:52 -08:00
winnerInfo_t winners[NB_LEVELS_TRACKED];
const char* const rfName = "grillResults.txt";
2016-07-12 04:42:10 -07:00
FILE* const f = fopen(rfName, "w");
2015-11-09 07:38:17 -08:00
const size_t blockSize = g_blockSize ? g_blockSize : srcSize;
2015-10-25 16:06:36 -07:00
/* init */
if (ctx==NULL) { DISPLAY("ZSTD_createCCtx() failed \n"); exit(1); }
memset(winners, 0, sizeof(winners));
if (f==NULL) { DISPLAY("error opening %s \n", rfName); exit(1); }
2016-02-10 04:37:52 -08:00
if (g_singleRun) {
2015-10-28 04:32:25 -07:00
BMK_result_t testResult;
2016-06-01 09:59:55 -07:00
g_params = ZSTD_adjustCParams(g_params, srcSize, 0);
2015-10-26 18:59:12 -07:00
BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, g_params);
DISPLAY("\n");
return;
}
2015-10-27 04:18:00 -07:00
if (g_target)
g_cSpeedTarget[1] = g_target * 1000000;
2016-02-10 04:37:52 -08:00
else {
2015-11-05 09:16:59 -08:00
/* baseline config for level 1 */
2015-10-28 04:32:25 -07:00
BMK_result_t testResult;
2016-03-30 11:42:19 -07:00
params = ZSTD_getCParams(1, blockSize, 0);
2015-10-27 04:18:00 -07:00
BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, params);
g_cSpeedTarget[1] = (testResult.cSpeed * 31) / 32;
2015-10-27 04:18:00 -07:00
}
2015-10-25 16:06:36 -07:00
2015-11-05 09:16:59 -08:00
/* establish speed objectives (relative to level 1) */
{ int i;
for (i=2; i<=ZSTD_maxCLevel(); i++)
g_cSpeedTarget[i] = (g_cSpeedTarget[i-1] * 25) / 32;
}
2015-10-26 07:45:58 -07:00
/* populate initial solution */
2016-07-12 04:42:10 -07:00
{ const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();
int i;
for (i=0; i<=maxSeeds; i++) {
2016-03-30 11:42:19 -07:00
params = ZSTD_getCParams(i, blockSize, 0);
2015-10-27 05:12:25 -07:00
BMK_seed(winners, params, srcBuffer, srcSize, ctx);
2016-07-12 04:42:10 -07:00
} }
2015-10-26 07:45:58 -07:00
BMK_printWinners(f, winners, srcSize);
/* start tests */
{ const time_t grillStart = time(NULL);
2016-02-10 04:37:52 -08:00
do {
2015-10-26 07:45:58 -07:00
BMK_selectRandomStart(f, winners, srcBuffer, srcSize, ctx);
} while (BMK_timeSpan(grillStart) < g_grillDuration_s);
2015-10-25 16:06:36 -07:00
}
/* end summary */
2015-10-26 07:45:58 -07:00
BMK_printWinners(f, winners, srcSize);
2015-10-27 04:18:00 -07:00
DISPLAY("grillParams operations completed \n");
2015-10-25 16:06:36 -07:00
/* clean up*/
2015-10-26 07:45:58 -07:00
fclose(f);
ZSTD_freeCCtx(ctx);
2015-10-25 16:06:36 -07:00
}
static int benchSample(void)
{
2016-02-10 04:37:52 -08:00
void* origBuff;
2016-07-12 04:42:10 -07:00
size_t const benchedSize = sampleSize;
const char* const name = "Sample 10MiB";
2015-10-25 16:06:36 -07:00
/* Allocation */
2016-02-10 04:37:52 -08:00
origBuff = malloc(benchedSize);
if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; }
2015-10-25 16:06:36 -07:00
/* Fill buffer */
RDG_genBuffer(origBuff, benchedSize, g_compressibility, 0.0, 0);
/* bench */
DISPLAY("\r%79s\r", "");
DISPLAY("using %s %i%%: \n", name, (int)(g_compressibility*100));
BMK_benchMem(origBuff, benchedSize);
free(origBuff);
return 0;
}
2016-07-12 04:42:10 -07:00
int benchFiles(const char** fileNamesTable, int nbFiles)
2015-10-25 16:06:36 -07:00
{
int fileIdx=0;
/* Loop for each file */
2016-02-10 04:37:52 -08:00
while (fileIdx<nbFiles) {
2016-07-12 04:42:10 -07:00
const char* const inFileName = fileNamesTable[fileIdx++];
FILE* const inFile = fopen( inFileName, "rb" );
U64 const inFileSize = UTIL_getFileSize(inFileName);
2015-10-25 16:06:36 -07:00
size_t benchedSize;
2016-07-12 04:42:10 -07:00
void* origBuff;
2015-10-25 16:06:36 -07:00
/* Check file existence */
2016-02-10 04:37:52 -08:00
if (inFile==NULL) {
2015-10-25 16:06:36 -07:00
DISPLAY( "Pb opening %s\n", inFileName);
return 11;
}
2016-07-12 04:42:10 -07:00
/* Memory allocation */
2016-02-10 04:37:52 -08:00
benchedSize = BMK_findMaxMem(inFileSize*3) / 3;
2015-10-25 16:06:36 -07:00
if ((U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize;
if (benchedSize < inFileSize)
DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", inFileName, (int)(benchedSize>>20));
2016-07-12 04:42:10 -07:00
origBuff = malloc(benchedSize);
if (origBuff==NULL) {
2015-10-25 16:06:36 -07:00
DISPLAY("\nError: not enough memory!\n");
fclose(inFile);
return 12;
}
/* Fill input buffer */
DISPLAY("Loading %s... \r", inFileName);
2016-07-12 04:42:10 -07:00
{ size_t const readSize = fread(origBuff, 1, benchedSize, inFile);
fclose(inFile);
if(readSize != benchedSize) {
DISPLAY("\nError: problem reading file '%s' !! \n", inFileName);
free(origBuff);
return 13;
} }
2015-10-25 16:06:36 -07:00
/* bench */
DISPLAY("\r%79s\r", "");
DISPLAY("using %s : \n", inFileName);
BMK_benchMem(origBuff, benchedSize);
2016-07-12 04:42:10 -07:00
/* clean */
free(origBuff);
2015-10-25 16:06:36 -07:00
}
return 0;
}
static void BMK_translateAdvancedParams(ZSTD_compressionParameters params)
{
DISPLAY("--zstd=windowLog=%u,chainLog=%u,hashLog=%u,searchLog=%u,searchLength=%u,targetLength=%u,strategy=%u \n",
params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength, params.targetLength, (U32)(params.strategy));
}
/* optimizeForSize():
* targetSpeed : expressed in MB/s */
int optimizeForSize(const char* inFileName, U32 targetSpeed)
2015-11-27 08:46:14 -08:00
{
FILE* const inFile = fopen( inFileName, "rb" );
U64 const inFileSize = UTIL_getFileSize(inFileName);
size_t benchedSize = BMK_findMaxMem(inFileSize*3) / 3;
void* origBuff;
/* Init */
if (inFile==NULL) { DISPLAY( "Pb opening %s\n", inFileName); return 11; }
2015-11-27 08:46:14 -08:00
/* Memory allocation & restrictions */
if ((U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize;
if (benchedSize < inFileSize) {
DISPLAY("Not enough memory for '%s' \n", inFileName);
fclose(inFile);
return 11;
}
2015-11-27 08:46:14 -08:00
/* Alloc */
origBuff = malloc(benchedSize);
2016-02-10 04:37:52 -08:00
if(!origBuff) {
2015-11-27 08:46:14 -08:00
DISPLAY("\nError: not enough memory!\n");
fclose(inFile);
return 12;
}
/* Fill input buffer */
DISPLAY("Loading %s... \r", inFileName);
{ size_t const readSize = fread(origBuff, 1, benchedSize, inFile);
fclose(inFile);
if(readSize != benchedSize) {
DISPLAY("\nError: problem reading file '%s' !! \n", inFileName);
free(origBuff);
return 13;
} }
2015-11-27 08:46:14 -08:00
/* bench */
DISPLAY("\r%79s\r", "");
DISPLAY("optimizing for %s - limit speed %u MB/s \n", inFileName, targetSpeed);
targetSpeed *= 1000000;
2015-11-27 08:46:14 -08:00
{ ZSTD_CCtx* const ctx = ZSTD_createCCtx();
2015-11-27 08:46:14 -08:00
winnerInfo_t winner;
BMK_result_t candidate;
const size_t blockSize = g_blockSize ? g_blockSize : benchedSize;
2015-11-27 08:46:14 -08:00
/* init */
if (ctx==NULL) { DISPLAY("\n ZSTD_createCCtx error \n"); free(origBuff); return 14;}
2015-11-27 08:46:14 -08:00
memset(&winner, 0, sizeof(winner));
winner.result.cSize = (size_t)(-1);
/* find best solution from default params */
2016-07-12 04:42:10 -07:00
{ const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();
int i;
2016-02-10 04:37:52 -08:00
for (i=1; i<=maxSeeds; i++) {
ZSTD_compressionParameters const CParams = ZSTD_getCParams(i, blockSize, 0);
BMK_benchParam(&candidate, origBuff, benchedSize, ctx, CParams);
if (candidate.cSpeed < targetSpeed)
break;
2015-11-27 08:46:14 -08:00
if ( (candidate.cSize < winner.result.cSize)
| ((candidate.cSize == winner.result.cSize) & (candidate.cSpeed > winner.result.cSpeed)) )
2015-11-27 08:46:14 -08:00
{
winner.params = CParams;
2015-11-27 08:46:14 -08:00
winner.result = candidate;
BMK_printWinner(stdout, i, winner.result, winner.params, benchedSize);
2016-02-10 04:37:52 -08:00
} }
2015-11-27 08:46:14 -08:00
}
BMK_printWinner(stdout, 99, winner.result, winner.params, benchedSize);
BMK_translateAdvancedParams(winner.params);
2015-11-27 08:46:14 -08:00
/* start tests */
{ time_t const grillStart = time(NULL);
2016-02-10 04:37:52 -08:00
do {
ZSTD_compressionParameters params = winner.params;
2015-11-27 08:46:14 -08:00
paramVariation(&params);
if ((FUZ_rand(&g_rand) & 31) == 3) params = randomParams(); /* totally random config to improve search space */
params = ZSTD_adjustCParams(params, blockSize, 0);
2015-11-27 08:46:14 -08:00
/* exclude faster if already played set of params */
if (FUZ_rand(&g_rand) & ((1 << NB_TESTS_PLAYED(params))-1)) continue;
/* test */
NB_TESTS_PLAYED(params)++;
BMK_benchParam(&candidate, origBuff, benchedSize, ctx, params);
2015-11-27 08:46:14 -08:00
/* improvement found => new winner */
if ( (candidate.cSpeed > targetSpeed)
& ( (candidate.cSize < winner.result.cSize)
| ((candidate.cSize == winner.result.cSize) & (candidate.cSpeed > winner.result.cSpeed)) ) )
{
2015-11-27 08:46:14 -08:00
winner.params = params;
winner.result = candidate;
BMK_printWinner(stdout, 99, winner.result, winner.params, benchedSize);
BMK_translateAdvancedParams(winner.params);
2015-11-27 08:46:14 -08:00
}
} while (BMK_timeSpan(grillStart) < g_grillDuration_s);
2015-11-27 08:46:14 -08:00
}
/* end summary */
BMK_printWinner(stdout, 99, winner.result, winner.params, benchedSize);
2015-11-27 08:46:14 -08:00
DISPLAY("grillParams size - optimizer completed \n");
/* clean up*/
ZSTD_freeCCtx(ctx);
}
free(origBuff);
2015-11-27 08:46:14 -08:00
return 0;
}
2016-07-12 04:42:10 -07:00
static int usage(const char* exename)
2015-10-25 16:06:36 -07:00
{
DISPLAY( "Usage :\n");
DISPLAY( " %s [arg] file\n", exename);
DISPLAY( "Arguments :\n");
2015-11-23 08:10:19 -08:00
DISPLAY( " file : path to the file used as reference (if none, generates a compressible sample)\n");
2015-10-25 16:06:36 -07:00
DISPLAY( " -H/-h : Help (this text + advanced options)\n");
return 0;
}
static int usage_advanced(void)
2015-10-25 16:06:36 -07:00
{
DISPLAY( "\nAdvanced options :\n");
2016-07-12 04:42:10 -07:00
DISPLAY( " -T# : set level 1 speed objective \n");
DISPLAY( " -B# : cut input into blocks of size # (default : single block) \n");
DISPLAY( " -i# : iteration loops [1-9](default : %i) \n", NBLOOPS);
DISPLAY( " -O# : find Optimized parameters for # MB/s compression speed (default : 0) \n");
2016-07-12 04:42:10 -07:00
DISPLAY( " -S : Single run \n");
DISPLAY( " -P# : generated sample compressibility (default : %.1f%%) \n", COMPRESSIBILITY_DEFAULT * 100);
2015-10-25 16:06:36 -07:00
return 0;
}
2016-07-12 04:42:10 -07:00
static int badusage(const char* exename)
2015-10-25 16:06:36 -07:00
{
DISPLAY("Wrong parameters\n");
usage(exename);
2015-10-26 18:59:12 -07:00
return 1;
2015-10-25 16:06:36 -07:00
}
2016-07-12 04:42:10 -07:00
int main(int argc, const char** argv)
2015-10-25 16:06:36 -07:00
{
int i,
filenamesStart=0,
result;
2016-07-12 04:42:10 -07:00
const char* exename=argv[0];
const char* input_filename=0;
2015-11-27 08:46:14 -08:00
U32 optimizer = 0;
2015-10-25 16:06:36 -07:00
U32 main_pause = 0;
U32 targetSpeed = 0;
2015-10-25 16:06:36 -07:00
2016-02-10 04:37:52 -08:00
/* checks */
if (NB_LEVELS_TRACKED <= ZSTD_maxCLevel()) {
DISPLAY("Error : NB_LEVELS_TRACKED <= ZSTD_maxCLevel() \n");
exit(1);
}
2015-10-25 16:06:36 -07:00
/* Welcome message */
DISPLAY(WELCOME_MESSAGE);
if (argc<1) { badusage(exename); return 1; }
2016-04-07 17:02:12 -07:00
for(i=1; i<argc; i++) {
2016-07-12 04:42:10 -07:00
const char* argument = argv[i];
2015-10-25 16:06:36 -07:00
2015-10-27 05:12:25 -07:00
if(!argument) continue; /* Protection if argument empty */
if(!strcmp(argument,"--no-seed")) { g_noSeed = 1; continue; }
2015-10-25 16:06:36 -07:00
2015-10-26 07:45:58 -07:00
/* Decode command (note : aggregated commands are allowed) */
2016-02-10 04:37:52 -08:00
if (argument[0]=='-') {
2015-10-26 18:59:12 -07:00
argument++;
2016-02-10 04:37:52 -08:00
while (argument[0]!=0) {
2015-10-25 16:06:36 -07:00
switch(argument[0])
{
/* Display help on usage */
case 'h' :
case 'H': usage(exename); usage_advanced(); return 0;
/* Pause at the end (hidden option) */
2015-10-26 18:59:12 -07:00
case 'p': main_pause = 1; argument++; break;
2015-10-25 16:06:36 -07:00
/* Modify Nb Iterations */
case 'i':
2015-10-26 18:59:12 -07:00
argument++;
if ((argument[0] >='0') & (argument[0] <='9'))
2015-10-30 07:49:48 -07:00
g_nbIterations = *argument++ - '0';
2015-10-25 16:06:36 -07:00
break;
/* Sample compressibility (when no file provided) */
case 'P':
2015-10-26 18:59:12 -07:00
argument++;
2016-04-07 17:02:12 -07:00
{ U32 proba32 = 0;
while ((argument[0]>= '0') & (argument[0]<= '9'))
2016-04-07 17:02:12 -07:00
proba32 = (proba32*10) + (*argument++ - '0');
2015-10-25 16:06:36 -07:00
g_compressibility = (double)proba32 / 100.;
}
break;
2015-11-27 08:46:14 -08:00
case 'O':
argument++;
optimizer=1;
targetSpeed = 0;
while ((*argument >= '0') & (*argument <= '9'))
targetSpeed = (targetSpeed*10) + (*argument++ - '0');
2015-11-27 08:46:14 -08:00
break;
2015-10-26 18:59:12 -07:00
/* Run Single conf */
case 'S':
2015-10-30 07:49:48 -07:00
g_singleRun = 1;
argument++;
2016-03-30 11:42:19 -07:00
g_params = ZSTD_getCParams(2, g_blockSize, 0);
2016-02-10 04:37:52 -08:00
for ( ; ; ) {
2015-10-30 07:49:48 -07:00
switch(*argument)
{
case 'w':
g_params.windowLog = 0;
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.windowLog *= 10, g_params.windowLog += *argument++ - '0';
continue;
case 'c':
2016-04-04 04:49:18 -07:00
g_params.chainLog = 0;
2015-10-30 07:49:48 -07:00
argument++;
while ((*argument>= '0') && (*argument<='9'))
2016-04-04 04:49:18 -07:00
g_params.chainLog *= 10, g_params.chainLog += *argument++ - '0';
2015-10-30 07:49:48 -07:00
continue;
case 'h':
g_params.hashLog = 0;
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.hashLog *= 10, g_params.hashLog += *argument++ - '0';
continue;
case 's':
g_params.searchLog = 0;
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.searchLog *= 10, g_params.searchLog += *argument++ - '0';
continue;
2015-11-01 03:40:22 -08:00
case 'l': /* search length */
2015-10-30 07:49:48 -07:00
g_params.searchLength = 0;
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.searchLength *= 10, g_params.searchLength += *argument++ - '0';
continue;
case 't': /* target length */
g_params.targetLength = 0;
2015-11-01 03:40:22 -08:00
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.targetLength *= 10, g_params.targetLength += *argument++ - '0';
continue;
case 'S': /* strategy */
argument++;
while ((*argument>= '0') && (*argument<='9'))
g_params.strategy = (ZSTD_strategy)(*argument++ - '0');
2015-11-01 03:40:22 -08:00
continue;
2015-10-30 07:49:48 -07:00
case 'L':
2016-04-07 17:02:12 -07:00
{ int cLevel = 0;
2015-10-30 07:49:48 -07:00
argument++;
while ((*argument>= '0') && (*argument<='9'))
cLevel *= 10, cLevel += *argument++ - '0';
2016-03-30 11:42:19 -07:00
g_params = ZSTD_getCParams(cLevel, g_blockSize, 0);
2015-10-30 07:49:48 -07:00
continue;
}
default : ;
}
2015-10-26 18:59:12 -07:00
break;
}
2015-10-30 07:49:48 -07:00
break;
2015-10-26 18:59:12 -07:00
2015-11-05 09:16:59 -08:00
/* target level1 speed objective, in MB/s */
2015-10-27 04:18:00 -07:00
case 'T':
argument++;
g_target = 0;
2016-04-07 17:02:12 -07:00
while ((*argument >= '0') && (*argument <= '9'))
g_target = (g_target*10) + (*argument++ - '0');
2015-10-27 04:18:00 -07:00
break;
/* cut input into blocks */
case 'B':
2016-04-07 17:02:12 -07:00
g_blockSize = 0;
argument++;
while ((*argument >='0') & (*argument <='9'))
2016-04-07 17:02:12 -07:00
g_blockSize = (g_blockSize*10) + (*argument++ - '0');
if (*argument=='K') g_blockSize<<=10, argument++; /* allows using KB notation */
if (*argument=='M') g_blockSize<<=20, argument++;
if (*argument=='B') argument++;
DISPLAY("using %u KB block size \n", g_blockSize>>10);
2015-10-27 04:18:00 -07:00
break;
2015-10-25 16:06:36 -07:00
/* Unknown command */
2015-10-26 18:59:12 -07:00
default : return badusage(exename);
2015-10-25 16:06:36 -07:00
}
}
continue;
2016-04-07 17:02:12 -07:00
} /* if (argument[0]=='-') */
2015-10-25 16:06:36 -07:00
/* first provided filename is input */
if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }
}
if (filenamesStart==0)
result = benchSample();
2016-02-10 04:37:52 -08:00
else {
2015-11-28 07:03:22 -08:00
if (optimizer)
result = optimizeForSize(input_filename, targetSpeed);
2015-11-28 07:03:22 -08:00
else
result = benchFiles(argv+filenamesStart, argc-filenamesStart);
}
2015-10-25 16:06:36 -07:00
if (main_pause) { int unused; printf("press enter...\n"); unused = getchar(); (void)unused; }
return result;
}