diff options
Diffstat (limited to 'programs/bench.c')
-rw-r--r-- | programs/bench.c | 228 |
1 files changed, 124 insertions, 104 deletions
diff --git a/programs/bench.c b/programs/bench.c index ec99c61cebf68..5d2568f104f50 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -34,14 +34,12 @@ #include <stdlib.h> /* malloc, free */ #include <string.h> /* memset */ #include <stdio.h> /* fprintf, fopen */ -#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */ #include "mem.h" #define ZSTD_STATIC_LINKING_ONLY #include "zstd.h" #include "datagen.h" /* RDG_genBuffer */ #include "xxhash.h" -#include "zstdmt_compress.h" /* ************************************* @@ -73,12 +71,13 @@ static U32 g_compressibilityDefault = 50; #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } static int g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */ -#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ - if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \ - { g_time = clock(); DISPLAY(__VA_ARGS__); \ - if (g_displayLevel>=4) fflush(stderr); } } -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; +static const U64 g_refreshRate = SEC_TO_MICRO / 6; +static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; + +#define DISPLAYUPDATE(l, ...) { if (g_displayLevel>=l) { \ + if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (g_displayLevel>=4)) \ + { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ + if (g_displayLevel>=4) fflush(stderr); } } } /* ************************************* @@ -130,6 +129,17 @@ void BMK_setNbThreads(unsigned nbThreads) { #endif g_nbThreads = nbThreads; } + +static U32 g_realTime = 0; +void BMK_setRealTime(unsigned priority) { + g_realTime = (priority>0); +} + +static U32 g_separateFiles = 0; +void BMK_setSeparateFiles(unsigned separate) { + g_separateFiles = (separate>0); +} + static U32 g_ldmFlag = 0; void BMK_setLdmFlag(unsigned ldmFlag) { g_ldmFlag = ldmFlag; @@ -181,7 +191,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, const char* displayName, int cLevel, const size_t* fileSizes, U32 nbFiles, const void* dictBuffer, size_t dictBufferSize, - const ZSTD_compressionParameters* comprParams) + const ZSTD_compressionParameters* const comprParams) { size_t const blockSize = ((g_blockSize>=32 && !g_decodeOnly) ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ; U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles; @@ -189,7 +199,6 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); /* add some room for safety */ void* const compressedBuffer = malloc(maxCompressedSize); void* resultBuffer = malloc(srcSize); - ZSTDMT_CCtx* const mtctx = ZSTDMT_createCCtx(g_nbThreads); ZSTD_CCtx* const ctx = ZSTD_createCCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx(); size_t const loadedCompressedSize = srcSize; @@ -286,8 +295,6 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, if (!cCompleted) { /* still some time to do compression tests */ U64 const clockLoop = g_nbSeconds ? TIMELOOP_MICROSEC : 1; U32 nbLoops = 0; - ZSTD_CDict* cdict = NULL; -#ifdef ZSTD_NEWAPI ZSTD_CCtx_setParameter(ctx, ZSTD_p_nbThreads, g_nbThreads); ZSTD_CCtx_setParameter(ctx, ZSTD_p_compressionLevel, cLevel); ZSTD_CCtx_setParameter(ctx, ZSTD_p_enableLongDistanceMatching, g_ldmFlag); @@ -306,84 +313,64 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, ZSTD_CCtx_setParameter(ctx, ZSTD_p_targetLength, comprParams->targetLength); ZSTD_CCtx_setParameter(ctx, ZSTD_p_compressionStrategy, comprParams->strategy); ZSTD_CCtx_loadDictionary(ctx, dictBuffer, dictBufferSize); -#else - size_t const avgSize = MIN(blockSize, (srcSize / nbFiles)); - ZSTD_parameters zparams = ZSTD_getParams(cLevel, avgSize, dictBufferSize); - ZSTD_customMem const cmem = { NULL, NULL, NULL }; - if (comprParams->windowLog) zparams.cParams.windowLog = comprParams->windowLog; - if (comprParams->chainLog) zparams.cParams.chainLog = comprParams->chainLog; - if (comprParams->hashLog) zparams.cParams.hashLog = comprParams->hashLog; - if (comprParams->searchLog) zparams.cParams.searchLog = comprParams->searchLog; - if (comprParams->searchLength) zparams.cParams.searchLength = comprParams->searchLength; - if (comprParams->targetLength) zparams.cParams.targetLength = comprParams->targetLength; - if (comprParams->strategy) zparams.cParams.strategy = comprParams->strategy; - cdict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dm_auto, zparams.cParams, cmem); - if (cdict==NULL) EXM_THROW(1, "ZSTD_createCDict_advanced() allocation failure"); -#endif do { U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) { - size_t rSize; -#ifdef ZSTD_NEWAPI - ZSTD_outBuffer out = { blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, 0 }; - ZSTD_inBuffer in = { blockTable[blockNb].srcPtr, blockTable[blockNb].srcSize, 0 }; - size_t cError = 1; - while (cError) { - cError = ZSTD_compress_generic(ctx, +#if 0 /* direct compression function, for occasional comparison */ + ZSTD_parameters const params = ZSTD_getParams(cLevel, blockTable[blockNb].srcSize, dictBufferSize); + blockTable[blockNb].cSize = ZSTD_compress_advanced(ctx, + blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, + blockTable[blockNb].srcPtr, blockTable[blockNb].srcSize, + dictBuffer, dictBufferSize, + params); +#else + size_t moreToFlush = 1; + ZSTD_outBuffer out; + ZSTD_inBuffer in; + in.src = blockTable[blockNb].srcPtr; + in.size = blockTable[blockNb].srcSize; + in.pos = 0; + out.dst = blockTable[blockNb].cPtr; + out.size = blockTable[blockNb].cRoom; + out.pos = 0; + while (moreToFlush) { + moreToFlush = ZSTD_compress_generic(ctx, &out, &in, ZSTD_e_end); - if (ZSTD_isError(cError)) + if (ZSTD_isError(moreToFlush)) EXM_THROW(1, "ZSTD_compress_generic() error : %s", - ZSTD_getErrorName(cError)); - } - rSize = out.pos; -#else /* ! ZSTD_NEWAPI */ - if (dictBufferSize) { - rSize = ZSTD_compress_usingCDict(ctx, - blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, - blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, - cdict); - } else { -# ifdef ZSTD_MULTITHREAD /* note : limitation : MT single-pass does not support compression with dictionary */ - rSize = ZSTDMT_compressCCtx(mtctx, - blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, - blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, - cLevel); -# else - rSize = ZSTD_compress_advanced (ctx, - blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, - blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, - NULL, 0, zparams); -# endif + ZSTD_getErrorName(moreToFlush)); } - if (ZSTD_isError(rSize)) - EXM_THROW(1, "ZSTD_compress_usingCDict() failed : %s", - ZSTD_getErrorName(rSize)); -#endif /* ZSTD_NEWAPI */ - blockTable[blockNb].cSize = rSize; + blockTable[blockNb].cSize = out.pos; +#endif } nbLoops++; } while (UTIL_clockSpanMicro(clockStart) < clockLoop); - ZSTD_freeCDict(cdict); - { U64 const clockSpanMicro = UTIL_clockSpanMicro(clockStart); - if (clockSpanMicro < fastestC*nbLoops) fastestC = clockSpanMicro / nbLoops; - totalCTime += clockSpanMicro; - cCompleted = (totalCTime >= maxTime); + { U64 const loopDuration = UTIL_clockSpanMicro(clockStart); + if (loopDuration < fastestC*nbLoops) + fastestC = loopDuration / nbLoops; + totalCTime += loopDuration; + cCompleted = (totalCTime >= maxTime); /* end compression tests */ } } cSize = 0; { U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) cSize += blockTable[blockNb].cSize; } ratio = (double)srcSize / (double)cSize; markNb = (markNb+1) % NB_MARKS; - DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s\r", - marks[markNb], displayName, (U32)srcSize, (U32)cSize, ratio, - (double)srcSize / fastestC ); + { int const ratioAccuracy = (ratio < 10.) ? 3 : 2; + double const compressionSpeed = (double)srcSize / fastestC; + int const cSpeedAccuracy = (compressionSpeed < 10.) ? 2 : 1; + DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f),%6.*f MB/s\r", + marks[markNb], displayName, (U32)srcSize, (U32)cSize, + ratioAccuracy, ratio, + cSpeedAccuracy, compressionSpeed ); + } } else { /* g_decodeOnly */ memcpy(compressedBuffer, srcBuffer, loadedCompressedSize); } #if 0 /* disable decompression test */ dCompleted=1; - (void)totalDTime; (void)fastestD; (void)crcOrig; /* unused when decompression disabled */ + (void)totalDTime; (void)fastestD; (void)crcOrig; /* unused when decompression disabled */ #else /* Decompression */ if (!dCompleted) memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */ @@ -413,17 +400,24 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, nbLoops++; } while (UTIL_clockSpanMicro(clockStart) < clockLoop); ZSTD_freeDDict(ddict); - { U64 const clockSpanMicro = UTIL_clockSpanMicro(clockStart); - if (clockSpanMicro < fastestD*nbLoops) fastestD = clockSpanMicro / nbLoops; - totalDTime += clockSpanMicro; + { U64 const loopDuration = UTIL_clockSpanMicro(clockStart); + if (loopDuration < fastestD*nbLoops) + fastestD = loopDuration / nbLoops; + totalDTime += loopDuration; dCompleted = (totalDTime >= maxTime); } } markNb = (markNb+1) % NB_MARKS; - DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s ,%6.1f MB/s\r", - marks[markNb], displayName, (U32)srcSize, (U32)cSize, ratio, - (double)srcSize / fastestC, - (double)srcSize / fastestD ); + { int const ratioAccuracy = (ratio < 10.) ? 3 : 2; + double const compressionSpeed = (double)srcSize / fastestC; + int const cSpeedAccuracy = (compressionSpeed < 10.) ? 2 : 1; + double const decompressionSpeed = (double)srcSize / fastestD; + DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f),%6.*f MB/s ,%6.1f MB/s \r", + marks[markNb], displayName, (U32)srcSize, (U32)cSize, + ratioAccuracy, ratio, + cSpeedAccuracy, compressionSpeed, + decompressionSpeed); + } /* CRC Checking */ { U64 const crcCheck = XXH64(resultBuffer, srcSize, 0); @@ -444,10 +438,12 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, DISPLAY("(sample %u, block %u, pos %u) \n", segNb, bNb, pos); if (u>5) { int n; + DISPLAY("origin: "); for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); DISPLAY(" :%02X: ", ((const BYTE*)srcBuffer)[u]); for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)srcBuffer)[u+n]); DISPLAY(" \n"); + DISPLAY("decode: "); for (n=-5; n<0; n++) DISPLAY("%02X ", ((const BYTE*)resultBuffer)[u+n]); DISPLAY(" :%02X: ", ((const BYTE*)resultBuffer)[u]); for (n=1; n<3; n++) DISPLAY("%02X ", ((const BYTE*)resultBuffer)[u+n]); @@ -463,7 +459,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, #endif } /* for (testNb = 1; testNb <= (g_nbSeconds + !g_nbSeconds); testNb++) */ - if (g_displayLevel == 1) { + if (g_displayLevel == 1) { /* hidden display mode -q, used by python speed benchmark */ double cSpeed = (double)srcSize / fastestC; double dSpeed = (double)srcSize / fastestD; if (g_additionalParam) @@ -478,7 +474,6 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize, free(blockTable); free(compressedBuffer); free(resultBuffer); - ZSTDMT_freeCCtx(mtctx); ZSTD_freeCCtx(ctx); ZSTD_freeDCtx(dctx); return 0; @@ -503,11 +498,11 @@ static size_t BMK_findMaxMem(U64 requiredMem) return (size_t)(requiredMem); } -static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize, +static void BMK_benchCLevel(const void* srcBuffer, size_t benchedSize, const char* displayName, int cLevel, int cLevelLast, const size_t* fileSizes, unsigned nbFiles, const void* dictBuffer, size_t dictBufferSize, - ZSTD_compressionParameters *compressionParams, int setRealTimePrio) + const ZSTD_compressionParameters* const compressionParams) { int l; @@ -515,8 +510,8 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize, if (!pch) pch = strrchr(displayName, '/'); /* Linux */ if (pch) displayName = pch+1; - if (setRealTimePrio) { - DISPLAYLEVEL(2, "Note : switching to a real-time priority \n"); + if (g_realTime) { + DISPLAYLEVEL(2, "Note : switching to real-time priority \n"); SET_REALTIME_PRIORITY; } @@ -539,7 +534,7 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize, At most, fills `buffer` entirely */ static void BMK_loadFiles(void* buffer, size_t bufferSize, size_t* fileSizes, - const char** fileNamesTable, unsigned nbFiles) + const char* const * const fileNamesTable, unsigned nbFiles) { size_t pos = 0, totalSize = 0; unsigned n; @@ -551,6 +546,11 @@ static void BMK_loadFiles(void* buffer, size_t bufferSize, fileSizes[n] = 0; continue; } + if (fileSize == UTIL_FILESIZE_UNKNOWN) { + DISPLAYLEVEL(2, "Cannot evaluate size of %s, ignoring ... \n", fileNamesTable[n]); + fileSizes[n] = 0; + continue; + } f = fopen(fileNamesTable[n], "rb"); if (f==NULL) EXM_THROW(10, "impossible to open file %s", fileNamesTable[n]); DISPLAYUPDATE(2, "Loading %s... \r", fileNamesTable[n]); @@ -566,26 +566,30 @@ static void BMK_loadFiles(void* buffer, size_t bufferSize, if (totalSize == 0) EXM_THROW(12, "no data to bench"); } -static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles, const char* dictFileName, int cLevel, - int cLevelLast, ZSTD_compressionParameters *compressionParams, int setRealTimePrio) +static void BMK_benchFileTable(const char* const * const fileNamesTable, unsigned const nbFiles, + const char* const dictFileName, + int const cLevel, int const cLevelLast, + const ZSTD_compressionParameters* const compressionParams) { void* srcBuffer; size_t benchedSize; void* dictBuffer = NULL; size_t dictBufferSize = 0; - size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t)); + size_t* const fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t)); U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles); - char mfName[20] = {0}; if (!fileSizes) EXM_THROW(12, "not enough memory for fileSizes"); /* Load dictionary */ if (dictFileName != NULL) { - U64 dictFileSize = UTIL_getFileSize(dictFileName); - if (dictFileSize > 64 MB) EXM_THROW(10, "dictionary file %s too large", dictFileName); + U64 const dictFileSize = UTIL_getFileSize(dictFileName); + if (dictFileSize > 64 MB) + EXM_THROW(10, "dictionary file %s too large", dictFileName); dictBufferSize = (size_t)dictFileSize; dictBuffer = malloc(dictBufferSize); - if (dictBuffer==NULL) EXM_THROW(11, "not enough memory for dictionary (%u bytes)", (U32)dictBufferSize); + if (dictBuffer==NULL) + EXM_THROW(11, "not enough memory for dictionary (%u bytes)", + (U32)dictBufferSize); BMK_loadFiles(dictBuffer, dictBufferSize, fileSizes, &dictFileName, 1); } @@ -601,13 +605,26 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles, co BMK_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles); /* Bench */ - snprintf (mfName, sizeof(mfName), " %u files", nbFiles); - { const char* displayName = (nbFiles > 1) ? mfName : fileNamesTable[0]; - BMK_benchCLevel(srcBuffer, benchedSize, - displayName, cLevel, cLevelLast, - fileSizes, nbFiles, - dictBuffer, dictBufferSize, compressionParams, setRealTimePrio); - } + if (g_separateFiles) { + const BYTE* srcPtr = (const BYTE*)srcBuffer; + U32 fileNb; + for (fileNb=0; fileNb<nbFiles; fileNb++) { + size_t const fileSize = fileSizes[fileNb]; + BMK_benchCLevel(srcPtr, fileSize, + fileNamesTable[fileNb], cLevel, cLevelLast, + fileSizes+fileNb, 1, + dictBuffer, dictBufferSize, compressionParams); + srcPtr += fileSize; + } + } else { + char mfName[20] = {0}; + snprintf (mfName, sizeof(mfName), " %u files", nbFiles); + { const char* const displayName = (nbFiles > 1) ? mfName : fileNamesTable[0]; + BMK_benchCLevel(srcBuffer, benchedSize, + displayName, cLevel, cLevelLast, + fileSizes, nbFiles, + dictBuffer, dictBufferSize, compressionParams); + } } /* clean up */ free(srcBuffer); @@ -616,7 +633,7 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles, co } -static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility, ZSTD_compressionParameters* compressionParams, int setRealTimePrio) +static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility, const ZSTD_compressionParameters* compressionParams) { char name[20] = {0}; size_t benchedSize = 10000000; @@ -630,15 +647,17 @@ static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility /* Bench */ snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100)); - BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0, compressionParams, setRealTimePrio); + BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0, compressionParams); /* clean up */ free(srcBuffer); } -int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, const char* dictFileName, - int cLevel, int cLevelLast, ZSTD_compressionParameters* compressionParams, int setRealTimePrio) +int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, + const char* dictFileName, + int cLevel, int cLevelLast, + const ZSTD_compressionParameters* compressionParams) { double const compressibility = (double)g_compressibilityDefault / 100; @@ -646,11 +665,12 @@ int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, const char* di if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel(); if (cLevelLast > ZSTD_maxCLevel()) cLevelLast = ZSTD_maxCLevel(); if (cLevelLast < cLevel) cLevelLast = cLevel; - if (cLevelLast > cLevel) DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); + if (cLevelLast > cLevel) + DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); if (nbFiles == 0) - BMK_syntheticTest(cLevel, cLevelLast, compressibility, compressionParams, setRealTimePrio); + BMK_syntheticTest(cLevel, cLevelLast, compressibility, compressionParams); else - BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast, compressionParams, setRealTimePrio); + BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast, compressionParams); return 0; } |