1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos 12*3117ece4Schristos /*_************************************ 13*3117ece4Schristos * Includes 14*3117ece4Schristos **************************************/ 15*3117ece4Schristos #define ZSTD_DISABLE_DEPRECATE_WARNINGS /* No deprecation warnings, we still bench some deprecated functions */ 16*3117ece4Schristos #include "util.h" /* Compiler options, UTIL_GetFileSize */ 17*3117ece4Schristos #include <stdlib.h> /* malloc */ 18*3117ece4Schristos #include <stdio.h> /* fprintf, fopen, ftello64 */ 19*3117ece4Schristos #include <assert.h> 20*3117ece4Schristos 21*3117ece4Schristos #include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */ 22*3117ece4Schristos #include "mem.h" /* U32 */ 23*3117ece4Schristos #ifndef ZSTD_DLL_IMPORT 24*3117ece4Schristos #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, ZSTD_getcBlockSize, blockType_e, KB, MB */ 25*3117ece4Schristos #include "decompress/zstd_decompress_internal.h" /* ZSTD_DCtx struct */ 26*3117ece4Schristos #else 27*3117ece4Schristos #define KB *(1 <<10) 28*3117ece4Schristos #define MB *(1 <<20) 29*3117ece4Schristos #define GB *(1U<<30) 30*3117ece4Schristos typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; 31*3117ece4Schristos #endif 32*3117ece4Schristos #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */ 33*3117ece4Schristos #include "zstd.h" /* ZSTD_versionString */ 34*3117ece4Schristos #include "util.h" /* time functions */ 35*3117ece4Schristos #include "datagen.h" 36*3117ece4Schristos #include "benchfn.h" /* CustomBench */ 37*3117ece4Schristos #include "benchzstd.h" /* MB_UNIT */ 38*3117ece4Schristos 39*3117ece4Schristos 40*3117ece4Schristos /*_************************************ 41*3117ece4Schristos * Constants 42*3117ece4Schristos **************************************/ 43*3117ece4Schristos #define PROGRAM_DESCRIPTION "Zstandard speed analyzer" 44*3117ece4Schristos #define AUTHOR "Yann Collet" 45*3117ece4Schristos #define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_versionString(), (int)(sizeof(void*)*8), AUTHOR, __DATE__ 46*3117ece4Schristos 47*3117ece4Schristos #define NBLOOPS 6 48*3117ece4Schristos #define TIMELOOP_S 2 49*3117ece4Schristos 50*3117ece4Schristos #define MAX_MEM (1984 MB) 51*3117ece4Schristos 52*3117ece4Schristos #define DEFAULT_CLEVEL 1 53*3117ece4Schristos 54*3117ece4Schristos #define COMPRESSIBILITY_DEFAULT 0.50 55*3117ece4Schristos static const size_t kSampleSizeDefault = 10000000; 56*3117ece4Schristos 57*3117ece4Schristos #define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ 58*3117ece4Schristos 59*3117ece4Schristos 60*3117ece4Schristos /*_************************************ 61*3117ece4Schristos * Macros 62*3117ece4Schristos **************************************/ 63*3117ece4Schristos #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) 64*3117ece4Schristos 65*3117ece4Schristos #define CONTROL(c) { if (!(c)) { abort(); } } /* like assert(), but cannot be disabled */ 66*3117ece4Schristos 67*3117ece4Schristos /*_************************************ 68*3117ece4Schristos * Benchmark Parameters 69*3117ece4Schristos **************************************/ 70*3117ece4Schristos static unsigned g_nbIterations = NBLOOPS; 71*3117ece4Schristos 72*3117ece4Schristos 73*3117ece4Schristos /*_******************************************************* 74*3117ece4Schristos * Private functions 75*3117ece4Schristos *********************************************************/ 76*3117ece4Schristos static size_t BMK_findMaxMem(U64 requiredMem) 77*3117ece4Schristos { 78*3117ece4Schristos size_t const step = 64 MB; 79*3117ece4Schristos void* testmem = NULL; 80*3117ece4Schristos 81*3117ece4Schristos requiredMem = (((requiredMem >> 26) + 1) << 26); 82*3117ece4Schristos if (requiredMem > MAX_MEM) requiredMem = MAX_MEM; 83*3117ece4Schristos 84*3117ece4Schristos requiredMem += step; 85*3117ece4Schristos do { 86*3117ece4Schristos testmem = malloc ((size_t)requiredMem); 87*3117ece4Schristos requiredMem -= step; 88*3117ece4Schristos } while (!testmem); 89*3117ece4Schristos 90*3117ece4Schristos free (testmem); 91*3117ece4Schristos return (size_t) requiredMem; 92*3117ece4Schristos } 93*3117ece4Schristos 94*3117ece4Schristos 95*3117ece4Schristos /*_******************************************************* 96*3117ece4Schristos * Benchmark wrappers 97*3117ece4Schristos *********************************************************/ 98*3117ece4Schristos 99*3117ece4Schristos static ZSTD_CCtx* g_zcc = NULL; 100*3117ece4Schristos 101*3117ece4Schristos static size_t 102*3117ece4Schristos local_ZSTD_compress(const void* src, size_t srcSize, 103*3117ece4Schristos void* dst, size_t dstSize, 104*3117ece4Schristos void* payload) 105*3117ece4Schristos { 106*3117ece4Schristos ZSTD_parameters p; 107*3117ece4Schristos ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 }; 108*3117ece4Schristos p.fParams = f; 109*3117ece4Schristos p.cParams = *(ZSTD_compressionParameters*)payload; 110*3117ece4Schristos return ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p); 111*3117ece4Schristos } 112*3117ece4Schristos 113*3117ece4Schristos static size_t 114*3117ece4Schristos local_ZSTD_compress_freshCCtx(const void* src, size_t srcSize, 115*3117ece4Schristos void* dst, size_t dstSize, 116*3117ece4Schristos void* payload) 117*3117ece4Schristos { 118*3117ece4Schristos ZSTD_parameters p; 119*3117ece4Schristos ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 }; 120*3117ece4Schristos p.fParams = f; 121*3117ece4Schristos p.cParams = *(ZSTD_compressionParameters*)payload; 122*3117ece4Schristos if (g_zcc != NULL) ZSTD_freeCCtx(g_zcc); 123*3117ece4Schristos g_zcc = ZSTD_createCCtx(); 124*3117ece4Schristos assert(g_zcc != NULL); 125*3117ece4Schristos { size_t const r = ZSTD_compress_advanced (g_zcc, dst, dstSize, src, srcSize, NULL ,0, p); 126*3117ece4Schristos ZSTD_freeCCtx(g_zcc); 127*3117ece4Schristos g_zcc = NULL; 128*3117ece4Schristos return r; 129*3117ece4Schristos } 130*3117ece4Schristos } 131*3117ece4Schristos 132*3117ece4Schristos static size_t g_cSize = 0; 133*3117ece4Schristos static size_t local_ZSTD_decompress(const void* src, size_t srcSize, 134*3117ece4Schristos void* dst, size_t dstSize, 135*3117ece4Schristos void* buff2) 136*3117ece4Schristos { 137*3117ece4Schristos (void)src; (void)srcSize; 138*3117ece4Schristos return ZSTD_decompress(dst, dstSize, buff2, g_cSize); 139*3117ece4Schristos } 140*3117ece4Schristos 141*3117ece4Schristos static ZSTD_DCtx* g_zdc = NULL; /* will be initialized within benchMem */ 142*3117ece4Schristos static size_t local_ZSTD_decompressDCtx(const void* src, size_t srcSize, 143*3117ece4Schristos void* dst, size_t dstSize, 144*3117ece4Schristos void* buff2) 145*3117ece4Schristos { 146*3117ece4Schristos (void)src; (void)srcSize; 147*3117ece4Schristos return ZSTD_decompressDCtx(g_zdc, dst, dstSize, buff2, g_cSize); 148*3117ece4Schristos } 149*3117ece4Schristos 150*3117ece4Schristos #ifndef ZSTD_DLL_IMPORT 151*3117ece4Schristos 152*3117ece4Schristos extern size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, 153*3117ece4Schristos const void* src, size_t srcSize, 154*3117ece4Schristos void* dst, size_t dstCapacity); 155*3117ece4Schristos static size_t local_ZSTD_decodeLiteralsBlock(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) 156*3117ece4Schristos { 157*3117ece4Schristos (void)src; (void)srcSize; (void)dst; (void)dstSize; 158*3117ece4Schristos return ZSTD_decodeLiteralsBlock_wrapper(g_zdc, buff2, g_cSize, dst, dstSize); 159*3117ece4Schristos } 160*3117ece4Schristos 161*3117ece4Schristos static size_t local_ZSTD_decodeSeqHeaders(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) 162*3117ece4Schristos { 163*3117ece4Schristos int nbSeq; 164*3117ece4Schristos (void)src; (void)srcSize; (void)dst; (void)dstSize; 165*3117ece4Schristos return ZSTD_decodeSeqHeaders(g_zdc, &nbSeq, buff2, g_cSize); 166*3117ece4Schristos } 167*3117ece4Schristos 168*3117ece4Schristos FORCE_NOINLINE size_t ZSTD_decodeLiteralsHeader(ZSTD_DCtx* dctx, void const* src, size_t srcSize) 169*3117ece4Schristos { 170*3117ece4Schristos RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); 171*3117ece4Schristos { 172*3117ece4Schristos BYTE const* istart = (BYTE const*)src; 173*3117ece4Schristos symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); 174*3117ece4Schristos if (litEncType == set_compressed) { 175*3117ece4Schristos RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3"); 176*3117ece4Schristos { 177*3117ece4Schristos size_t lhSize, litSize, litCSize; 178*3117ece4Schristos U32 const lhlCode = (istart[0] >> 2) & 3; 179*3117ece4Schristos U32 const lhc = MEM_readLE32(istart); 180*3117ece4Schristos int const flags = ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0; 181*3117ece4Schristos switch(lhlCode) 182*3117ece4Schristos { 183*3117ece4Schristos case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */ 184*3117ece4Schristos /* 2 - 2 - 10 - 10 */ 185*3117ece4Schristos lhSize = 3; 186*3117ece4Schristos litSize = (lhc >> 4) & 0x3FF; 187*3117ece4Schristos litCSize = (lhc >> 14) & 0x3FF; 188*3117ece4Schristos break; 189*3117ece4Schristos case 2: 190*3117ece4Schristos /* 2 - 2 - 14 - 14 */ 191*3117ece4Schristos lhSize = 4; 192*3117ece4Schristos litSize = (lhc >> 4) & 0x3FFF; 193*3117ece4Schristos litCSize = lhc >> 18; 194*3117ece4Schristos break; 195*3117ece4Schristos case 3: 196*3117ece4Schristos /* 2 - 2 - 18 - 18 */ 197*3117ece4Schristos lhSize = 5; 198*3117ece4Schristos litSize = (lhc >> 4) & 0x3FFFF; 199*3117ece4Schristos litCSize = (lhc >> 22) + ((size_t)istart[4] << 10); 200*3117ece4Schristos break; 201*3117ece4Schristos } 202*3117ece4Schristos RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); 203*3117ece4Schristos RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, ""); 204*3117ece4Schristos #ifndef HUF_FORCE_DECOMPRESS_X2 205*3117ece4Schristos return HUF_readDTableX1_wksp( 206*3117ece4Schristos dctx->entropy.hufTable, 207*3117ece4Schristos istart+lhSize, litCSize, 208*3117ece4Schristos dctx->workspace, sizeof(dctx->workspace), 209*3117ece4Schristos flags); 210*3117ece4Schristos #else 211*3117ece4Schristos return HUF_readDTableX2_wksp( 212*3117ece4Schristos dctx->entropy.hufTable, 213*3117ece4Schristos istart+lhSize, litCSize, 214*3117ece4Schristos dctx->workspace, sizeof(dctx->workspace), flags); 215*3117ece4Schristos #endif 216*3117ece4Schristos } 217*3117ece4Schristos } 218*3117ece4Schristos } 219*3117ece4Schristos return 0; 220*3117ece4Schristos } 221*3117ece4Schristos 222*3117ece4Schristos static size_t local_ZSTD_decodeLiteralsHeader(const void* src, size_t srcSize, void* dst, size_t dstSize, void* buff2) 223*3117ece4Schristos { 224*3117ece4Schristos (void)dst, (void)dstSize, (void)src, (void)srcSize; 225*3117ece4Schristos return ZSTD_decodeLiteralsHeader(g_zdc, buff2, g_cSize); 226*3117ece4Schristos } 227*3117ece4Schristos #endif 228*3117ece4Schristos 229*3117ece4Schristos static ZSTD_CStream* g_cstream= NULL; 230*3117ece4Schristos static size_t 231*3117ece4Schristos local_ZSTD_compressStream(const void* src, size_t srcSize, 232*3117ece4Schristos void* dst, size_t dstCapacity, 233*3117ece4Schristos void* payload) 234*3117ece4Schristos { 235*3117ece4Schristos ZSTD_outBuffer buffOut; 236*3117ece4Schristos ZSTD_inBuffer buffIn; 237*3117ece4Schristos ZSTD_parameters p; 238*3117ece4Schristos ZSTD_frameParameters f = {1 /* contentSizeHeader*/, 0, 0}; 239*3117ece4Schristos p.fParams = f; 240*3117ece4Schristos p.cParams = *(ZSTD_compressionParameters*)payload; 241*3117ece4Schristos ZSTD_initCStream_advanced(g_cstream, NULL, 0, p, ZSTD_CONTENTSIZE_UNKNOWN); 242*3117ece4Schristos buffOut.dst = dst; 243*3117ece4Schristos buffOut.size = dstCapacity; 244*3117ece4Schristos buffOut.pos = 0; 245*3117ece4Schristos buffIn.src = src; 246*3117ece4Schristos buffIn.size = srcSize; 247*3117ece4Schristos buffIn.pos = 0; 248*3117ece4Schristos ZSTD_compressStream(g_cstream, &buffOut, &buffIn); 249*3117ece4Schristos ZSTD_endStream(g_cstream, &buffOut); 250*3117ece4Schristos return buffOut.pos; 251*3117ece4Schristos } 252*3117ece4Schristos 253*3117ece4Schristos static size_t 254*3117ece4Schristos local_ZSTD_compressStream_freshCCtx(const void* src, size_t srcSize, 255*3117ece4Schristos void* dst, size_t dstCapacity, 256*3117ece4Schristos void* payload) 257*3117ece4Schristos { 258*3117ece4Schristos if (g_cstream != NULL) ZSTD_freeCCtx(g_cstream); 259*3117ece4Schristos g_cstream = ZSTD_createCCtx(); 260*3117ece4Schristos assert(g_cstream != NULL); 261*3117ece4Schristos 262*3117ece4Schristos { size_t const r = local_ZSTD_compressStream(src, srcSize, dst, dstCapacity, payload); 263*3117ece4Schristos ZSTD_freeCCtx(g_cstream); 264*3117ece4Schristos g_cstream = NULL; 265*3117ece4Schristos return r; 266*3117ece4Schristos } 267*3117ece4Schristos } 268*3117ece4Schristos 269*3117ece4Schristos static size_t 270*3117ece4Schristos local_ZSTD_compress2(const void* src, size_t srcSize, 271*3117ece4Schristos void* dst, size_t dstCapacity, 272*3117ece4Schristos void* payload) 273*3117ece4Schristos { 274*3117ece4Schristos (void)payload; 275*3117ece4Schristos return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize); 276*3117ece4Schristos } 277*3117ece4Schristos 278*3117ece4Schristos static size_t 279*3117ece4Schristos local_ZSTD_compressStream2_end(const void* src, size_t srcSize, 280*3117ece4Schristos void* dst, size_t dstCapacity, 281*3117ece4Schristos void* payload) 282*3117ece4Schristos { 283*3117ece4Schristos ZSTD_outBuffer buffOut; 284*3117ece4Schristos ZSTD_inBuffer buffIn; 285*3117ece4Schristos (void)payload; 286*3117ece4Schristos buffOut.dst = dst; 287*3117ece4Schristos buffOut.size = dstCapacity; 288*3117ece4Schristos buffOut.pos = 0; 289*3117ece4Schristos buffIn.src = src; 290*3117ece4Schristos buffIn.size = srcSize; 291*3117ece4Schristos buffIn.pos = 0; 292*3117ece4Schristos ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end); 293*3117ece4Schristos return buffOut.pos; 294*3117ece4Schristos } 295*3117ece4Schristos 296*3117ece4Schristos static size_t 297*3117ece4Schristos local_ZSTD_compressStream2_continue(const void* src, size_t srcSize, 298*3117ece4Schristos void* dst, size_t dstCapacity, 299*3117ece4Schristos void* payload) 300*3117ece4Schristos { 301*3117ece4Schristos ZSTD_outBuffer buffOut; 302*3117ece4Schristos ZSTD_inBuffer buffIn; 303*3117ece4Schristos (void)payload; 304*3117ece4Schristos buffOut.dst = dst; 305*3117ece4Schristos buffOut.size = dstCapacity; 306*3117ece4Schristos buffOut.pos = 0; 307*3117ece4Schristos buffIn.src = src; 308*3117ece4Schristos buffIn.size = srcSize; 309*3117ece4Schristos buffIn.pos = 0; 310*3117ece4Schristos ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_continue); 311*3117ece4Schristos ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end); 312*3117ece4Schristos return buffOut.pos; 313*3117ece4Schristos } 314*3117ece4Schristos 315*3117ece4Schristos static size_t 316*3117ece4Schristos local_ZSTD_compress_generic_T2_end(const void* src, size_t srcSize, 317*3117ece4Schristos void* dst, size_t dstCapacity, 318*3117ece4Schristos void* payload) 319*3117ece4Schristos { 320*3117ece4Schristos (void)payload; 321*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2); 322*3117ece4Schristos return ZSTD_compress2(g_cstream, dst, dstCapacity, src, srcSize); 323*3117ece4Schristos } 324*3117ece4Schristos 325*3117ece4Schristos static size_t 326*3117ece4Schristos local_ZSTD_compress_generic_T2_continue(const void* src, size_t srcSize, 327*3117ece4Schristos void* dst, size_t dstCapacity, 328*3117ece4Schristos void* payload) 329*3117ece4Schristos { 330*3117ece4Schristos ZSTD_outBuffer buffOut; 331*3117ece4Schristos ZSTD_inBuffer buffIn; 332*3117ece4Schristos (void)payload; 333*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_nbWorkers, 2); 334*3117ece4Schristos buffOut.dst = dst; 335*3117ece4Schristos buffOut.size = dstCapacity; 336*3117ece4Schristos buffOut.pos = 0; 337*3117ece4Schristos buffIn.src = src; 338*3117ece4Schristos buffIn.size = srcSize; 339*3117ece4Schristos buffIn.pos = 0; 340*3117ece4Schristos ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_continue); 341*3117ece4Schristos while(ZSTD_compressStream2(g_cstream, &buffOut, &buffIn, ZSTD_e_end)) {} 342*3117ece4Schristos return buffOut.pos; 343*3117ece4Schristos } 344*3117ece4Schristos 345*3117ece4Schristos static ZSTD_DStream* g_dstream= NULL; 346*3117ece4Schristos static size_t 347*3117ece4Schristos local_ZSTD_decompressStream(const void* src, size_t srcSize, 348*3117ece4Schristos void* dst, size_t dstCapacity, 349*3117ece4Schristos void* buff2) 350*3117ece4Schristos { 351*3117ece4Schristos ZSTD_outBuffer buffOut; 352*3117ece4Schristos ZSTD_inBuffer buffIn; 353*3117ece4Schristos (void)src; (void)srcSize; 354*3117ece4Schristos ZSTD_initDStream(g_dstream); 355*3117ece4Schristos buffOut.dst = dst; 356*3117ece4Schristos buffOut.size = dstCapacity; 357*3117ece4Schristos buffOut.pos = 0; 358*3117ece4Schristos buffIn.src = buff2; 359*3117ece4Schristos buffIn.size = g_cSize; 360*3117ece4Schristos buffIn.pos = 0; 361*3117ece4Schristos ZSTD_decompressStream(g_dstream, &buffOut, &buffIn); 362*3117ece4Schristos return buffOut.pos; 363*3117ece4Schristos } 364*3117ece4Schristos 365*3117ece4Schristos #ifndef ZSTD_DLL_IMPORT 366*3117ece4Schristos static size_t local_ZSTD_compressContinue(const void* src, size_t srcSize, 367*3117ece4Schristos void* dst, size_t dstCapacity, 368*3117ece4Schristos void* payload) 369*3117ece4Schristos { 370*3117ece4Schristos ZSTD_parameters p; 371*3117ece4Schristos ZSTD_frameParameters f = { 1 /* contentSizeHeader*/, 0, 0 }; 372*3117ece4Schristos p.fParams = f; 373*3117ece4Schristos p.cParams = *(ZSTD_compressionParameters*)payload; 374*3117ece4Schristos ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize); 375*3117ece4Schristos return ZSTD_compressEnd(g_zcc, dst, dstCapacity, src, srcSize); 376*3117ece4Schristos } 377*3117ece4Schristos 378*3117ece4Schristos #define FIRST_BLOCK_SIZE 8 379*3117ece4Schristos static size_t 380*3117ece4Schristos local_ZSTD_compressContinue_extDict(const void* src, size_t srcSize, 381*3117ece4Schristos void* dst, size_t dstCapacity, 382*3117ece4Schristos void* payload) 383*3117ece4Schristos { 384*3117ece4Schristos BYTE firstBlockBuf[FIRST_BLOCK_SIZE]; 385*3117ece4Schristos 386*3117ece4Schristos ZSTD_parameters p; 387*3117ece4Schristos ZSTD_frameParameters const f = { 1, 0, 0 }; 388*3117ece4Schristos p.fParams = f; 389*3117ece4Schristos p.cParams = *(ZSTD_compressionParameters*)payload; 390*3117ece4Schristos ZSTD_compressBegin_advanced(g_zcc, NULL, 0, p, srcSize); 391*3117ece4Schristos memcpy(firstBlockBuf, src, FIRST_BLOCK_SIZE); 392*3117ece4Schristos 393*3117ece4Schristos { size_t const compressResult = ZSTD_compressContinue(g_zcc, 394*3117ece4Schristos dst, dstCapacity, 395*3117ece4Schristos firstBlockBuf, FIRST_BLOCK_SIZE); 396*3117ece4Schristos if (ZSTD_isError(compressResult)) { 397*3117ece4Schristos DISPLAY("local_ZSTD_compressContinue_extDict error : %s\n", 398*3117ece4Schristos ZSTD_getErrorName(compressResult)); 399*3117ece4Schristos return compressResult; 400*3117ece4Schristos } 401*3117ece4Schristos dst = (BYTE*)dst + compressResult; 402*3117ece4Schristos dstCapacity -= compressResult; 403*3117ece4Schristos } 404*3117ece4Schristos return ZSTD_compressEnd(g_zcc, dst, dstCapacity, 405*3117ece4Schristos (const BYTE*)src + FIRST_BLOCK_SIZE, 406*3117ece4Schristos srcSize - FIRST_BLOCK_SIZE); 407*3117ece4Schristos } 408*3117ece4Schristos 409*3117ece4Schristos static size_t local_ZSTD_decompressContinue(const void* src, size_t srcSize, 410*3117ece4Schristos void* dst, size_t dstCapacity, 411*3117ece4Schristos void* buff2) 412*3117ece4Schristos { 413*3117ece4Schristos size_t regeneratedSize = 0; 414*3117ece4Schristos const BYTE* ip = (const BYTE*)buff2; 415*3117ece4Schristos const BYTE* const iend = ip + g_cSize; 416*3117ece4Schristos BYTE* op = (BYTE*)dst; 417*3117ece4Schristos size_t remainingCapacity = dstCapacity; 418*3117ece4Schristos 419*3117ece4Schristos (void)src; (void)srcSize; /* unused */ 420*3117ece4Schristos ZSTD_decompressBegin(g_zdc); 421*3117ece4Schristos while (ip < iend) { 422*3117ece4Schristos size_t const iSize = ZSTD_nextSrcSizeToDecompress(g_zdc); 423*3117ece4Schristos size_t const decodedSize = ZSTD_decompressContinue(g_zdc, op, remainingCapacity, ip, iSize); 424*3117ece4Schristos ip += iSize; 425*3117ece4Schristos regeneratedSize += decodedSize; 426*3117ece4Schristos op += decodedSize; 427*3117ece4Schristos remainingCapacity -= decodedSize; 428*3117ece4Schristos } 429*3117ece4Schristos 430*3117ece4Schristos return regeneratedSize; 431*3117ece4Schristos } 432*3117ece4Schristos #endif 433*3117ece4Schristos 434*3117ece4Schristos 435*3117ece4Schristos /*_******************************************************* 436*3117ece4Schristos * Bench functions 437*3117ece4Schristos *********************************************************/ 438*3117ece4Schristos static int benchMem(unsigned benchNb, 439*3117ece4Schristos const void* src, size_t srcSize, 440*3117ece4Schristos int cLevel, ZSTD_compressionParameters cparams) 441*3117ece4Schristos { 442*3117ece4Schristos size_t dstBuffSize = ZSTD_compressBound(srcSize); 443*3117ece4Schristos BYTE* dstBuff; 444*3117ece4Schristos void* dstBuff2; 445*3117ece4Schristos void* payload; 446*3117ece4Schristos const char* benchName; 447*3117ece4Schristos BMK_benchFn_t benchFunction; 448*3117ece4Schristos int errorcode = 0; 449*3117ece4Schristos 450*3117ece4Schristos /* Selection */ 451*3117ece4Schristos switch(benchNb) 452*3117ece4Schristos { 453*3117ece4Schristos case 1: 454*3117ece4Schristos benchFunction = local_ZSTD_compress; benchName = "compress"; 455*3117ece4Schristos break; 456*3117ece4Schristos case 2: 457*3117ece4Schristos benchFunction = local_ZSTD_decompress; benchName = "decompress"; 458*3117ece4Schristos break; 459*3117ece4Schristos case 3: 460*3117ece4Schristos benchFunction = local_ZSTD_compress_freshCCtx; benchName = "compress_freshCCtx"; 461*3117ece4Schristos break; 462*3117ece4Schristos case 4: 463*3117ece4Schristos benchFunction = local_ZSTD_decompressDCtx; benchName = "decompressDCtx"; 464*3117ece4Schristos break; 465*3117ece4Schristos #ifndef ZSTD_DLL_IMPORT 466*3117ece4Schristos case 11: 467*3117ece4Schristos benchFunction = local_ZSTD_compressContinue; benchName = "compressContinue"; 468*3117ece4Schristos break; 469*3117ece4Schristos case 12: 470*3117ece4Schristos benchFunction = local_ZSTD_compressContinue_extDict; benchName = "compressContinue_extDict"; 471*3117ece4Schristos break; 472*3117ece4Schristos case 13: 473*3117ece4Schristos benchFunction = local_ZSTD_decompressContinue; benchName = "decompressContinue"; 474*3117ece4Schristos break; 475*3117ece4Schristos case 30: 476*3117ece4Schristos benchFunction = local_ZSTD_decodeLiteralsHeader; benchName = "decodeLiteralsHeader"; 477*3117ece4Schristos break; 478*3117ece4Schristos case 31: 479*3117ece4Schristos benchFunction = local_ZSTD_decodeLiteralsBlock; benchName = "decodeLiteralsBlock"; 480*3117ece4Schristos break; 481*3117ece4Schristos case 32: 482*3117ece4Schristos benchFunction = local_ZSTD_decodeSeqHeaders; benchName = "decodeSeqHeaders"; 483*3117ece4Schristos break; 484*3117ece4Schristos #endif 485*3117ece4Schristos case 41: 486*3117ece4Schristos benchFunction = local_ZSTD_compressStream; benchName = "compressStream"; 487*3117ece4Schristos break; 488*3117ece4Schristos case 42: 489*3117ece4Schristos benchFunction = local_ZSTD_decompressStream; benchName = "decompressStream"; 490*3117ece4Schristos break; 491*3117ece4Schristos case 43: 492*3117ece4Schristos benchFunction = local_ZSTD_compressStream_freshCCtx; benchName = "compressStream_freshCCtx"; 493*3117ece4Schristos break; 494*3117ece4Schristos case 50: 495*3117ece4Schristos benchFunction = local_ZSTD_compress2; benchName = "compress2"; 496*3117ece4Schristos break; 497*3117ece4Schristos case 51: 498*3117ece4Schristos benchFunction = local_ZSTD_compressStream2_end; benchName = "compressStream2, end"; 499*3117ece4Schristos break; 500*3117ece4Schristos case 52: 501*3117ece4Schristos benchFunction = local_ZSTD_compressStream2_end; benchName = "compressStream2, end & short"; 502*3117ece4Schristos break; 503*3117ece4Schristos case 53: 504*3117ece4Schristos benchFunction = local_ZSTD_compressStream2_continue; benchName = "compressStream2, continue"; 505*3117ece4Schristos break; 506*3117ece4Schristos case 61: 507*3117ece4Schristos benchFunction = local_ZSTD_compress_generic_T2_continue; benchName = "compress_generic, -T2, continue"; 508*3117ece4Schristos break; 509*3117ece4Schristos case 62: 510*3117ece4Schristos benchFunction = local_ZSTD_compress_generic_T2_end; benchName = "compress_generic, -T2, end"; 511*3117ece4Schristos break; 512*3117ece4Schristos default : 513*3117ece4Schristos return 0; 514*3117ece4Schristos } 515*3117ece4Schristos 516*3117ece4Schristos /* Allocation */ 517*3117ece4Schristos dstBuff = (BYTE*)malloc(dstBuffSize); 518*3117ece4Schristos dstBuff2 = malloc(dstBuffSize); 519*3117ece4Schristos if ((!dstBuff) || (!dstBuff2)) { 520*3117ece4Schristos DISPLAY("\nError: not enough memory!\n"); 521*3117ece4Schristos free(dstBuff); free(dstBuff2); 522*3117ece4Schristos return 12; 523*3117ece4Schristos } 524*3117ece4Schristos payload = dstBuff2; 525*3117ece4Schristos if (g_zcc==NULL) g_zcc = ZSTD_createCCtx(); 526*3117ece4Schristos if (g_zdc==NULL) g_zdc = ZSTD_createDCtx(); 527*3117ece4Schristos if (g_cstream==NULL) g_cstream = ZSTD_createCStream(); 528*3117ece4Schristos if (g_dstream==NULL) g_dstream = ZSTD_createDStream(); 529*3117ece4Schristos 530*3117ece4Schristos /* DISPLAY("params: cLevel %d, wlog %d hlog %d clog %d slog %d mml %d tlen %d strat %d \n", 531*3117ece4Schristos cLevel, cparams->windowLog, cparams->hashLog, cparams->chainLog, cparams->searchLog, 532*3117ece4Schristos cparams->minMatch, cparams->targetLength, cparams->strategy); */ 533*3117ece4Schristos 534*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_compressionLevel, cLevel); 535*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_windowLog, (int)cparams.windowLog); 536*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_hashLog, (int)cparams.hashLog); 537*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_chainLog, (int)cparams.chainLog); 538*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_searchLog, (int)cparams.searchLog); 539*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_minMatch, (int)cparams.minMatch); 540*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_targetLength, (int)cparams.targetLength); 541*3117ece4Schristos ZSTD_CCtx_setParameter(g_zcc, ZSTD_c_strategy, cparams.strategy); 542*3117ece4Schristos 543*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_compressionLevel, cLevel); 544*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_windowLog, (int)cparams.windowLog); 545*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_hashLog, (int)cparams.hashLog); 546*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_chainLog, (int)cparams.chainLog); 547*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_searchLog, (int)cparams.searchLog); 548*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_minMatch, (int)cparams.minMatch); 549*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_targetLength, (int)cparams.targetLength); 550*3117ece4Schristos ZSTD_CCtx_setParameter(g_cstream, ZSTD_c_strategy, cparams.strategy); 551*3117ece4Schristos 552*3117ece4Schristos /* Preparation */ 553*3117ece4Schristos switch(benchNb) 554*3117ece4Schristos { 555*3117ece4Schristos case 1: 556*3117ece4Schristos payload = &cparams; 557*3117ece4Schristos break; 558*3117ece4Schristos case 2: 559*3117ece4Schristos g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); 560*3117ece4Schristos break; 561*3117ece4Schristos case 3: 562*3117ece4Schristos payload = &cparams; 563*3117ece4Schristos break; 564*3117ece4Schristos case 4: 565*3117ece4Schristos g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); 566*3117ece4Schristos break; 567*3117ece4Schristos #ifndef ZSTD_DLL_IMPORT 568*3117ece4Schristos case 11: 569*3117ece4Schristos payload = &cparams; 570*3117ece4Schristos break; 571*3117ece4Schristos case 12: 572*3117ece4Schristos payload = &cparams; 573*3117ece4Schristos break; 574*3117ece4Schristos case 13 : 575*3117ece4Schristos g_cSize = ZSTD_compress(dstBuff2, dstBuffSize, src, srcSize, cLevel); 576*3117ece4Schristos break; 577*3117ece4Schristos case 30: /* ZSTD_decodeLiteralsHeader */ 578*3117ece4Schristos /* fall-through */ 579*3117ece4Schristos case 31: /* ZSTD_decodeLiteralsBlock : starts literals block in dstBuff2 */ 580*3117ece4Schristos { size_t frameHeaderSize; 581*3117ece4Schristos g_cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); 582*3117ece4Schristos frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); 583*3117ece4Schristos CONTROL(!ZSTD_isError(frameHeaderSize)); 584*3117ece4Schristos /* check block is compressible, hence contains a literals section */ 585*3117ece4Schristos { blockProperties_t bp; 586*3117ece4Schristos ZSTD_getcBlockSize(dstBuff+frameHeaderSize, dstBuffSize, &bp); /* Get 1st block type */ 587*3117ece4Schristos if (bp.blockType != bt_compressed) { 588*3117ece4Schristos DISPLAY("ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible)\n"); 589*3117ece4Schristos goto _cleanOut; 590*3117ece4Schristos } } 591*3117ece4Schristos { size_t const skippedSize = frameHeaderSize + ZSTD_blockHeaderSize; 592*3117ece4Schristos memcpy(dstBuff2, dstBuff+skippedSize, g_cSize-skippedSize); 593*3117ece4Schristos } 594*3117ece4Schristos srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ 595*3117ece4Schristos ZSTD_decompressBegin(g_zdc); 596*3117ece4Schristos break; 597*3117ece4Schristos } 598*3117ece4Schristos case 32: /* ZSTD_decodeSeqHeaders */ 599*3117ece4Schristos { blockProperties_t bp; 600*3117ece4Schristos const BYTE* ip = dstBuff; 601*3117ece4Schristos const BYTE* iend; 602*3117ece4Schristos { size_t const cSize = ZSTD_compress(dstBuff, dstBuffSize, src, srcSize, cLevel); 603*3117ece4Schristos CONTROL(cSize > ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); 604*3117ece4Schristos } 605*3117ece4Schristos /* Skip frame Header */ 606*3117ece4Schristos { size_t const frameHeaderSize = ZSTD_frameHeaderSize(dstBuff, ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_f_zstd1)); 607*3117ece4Schristos CONTROL(!ZSTD_isError(frameHeaderSize)); 608*3117ece4Schristos ip += frameHeaderSize; 609*3117ece4Schristos } 610*3117ece4Schristos /* Find end of block */ 611*3117ece4Schristos { size_t const cBlockSize = ZSTD_getcBlockSize(ip, dstBuffSize, &bp); /* Get 1st block type */ 612*3117ece4Schristos if (bp.blockType != bt_compressed) { 613*3117ece4Schristos DISPLAY("ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible)\n"); 614*3117ece4Schristos goto _cleanOut; 615*3117ece4Schristos } 616*3117ece4Schristos iend = ip + ZSTD_blockHeaderSize + cBlockSize; /* End of first block */ 617*3117ece4Schristos } 618*3117ece4Schristos ip += ZSTD_blockHeaderSize; /* skip block header */ 619*3117ece4Schristos ZSTD_decompressBegin(g_zdc); 620*3117ece4Schristos CONTROL(iend > ip); 621*3117ece4Schristos ip += ZSTD_decodeLiteralsBlock_wrapper(g_zdc, ip, (size_t)(iend-ip), dstBuff, dstBuffSize); /* skip literal segment */ 622*3117ece4Schristos g_cSize = (size_t)(iend-ip); 623*3117ece4Schristos memcpy(dstBuff2, ip, g_cSize); /* copy rest of block (it starts by SeqHeader) */ 624*3117ece4Schristos srcSize = srcSize > 128 KB ? 128 KB : srcSize; /* speed relative to block */ 625*3117ece4Schristos break; 626*3117ece4Schristos } 627*3117ece4Schristos #else 628*3117ece4Schristos case 31: 629*3117ece4Schristos goto _cleanOut; 630*3117ece4Schristos #endif 631*3117ece4Schristos case 41 : 632*3117ece4Schristos payload = &cparams; 633*3117ece4Schristos break; 634*3117ece4Schristos case 42 : 635*3117ece4Schristos g_cSize = ZSTD_compress(payload, dstBuffSize, src, srcSize, cLevel); 636*3117ece4Schristos break; 637*3117ece4Schristos case 43 : 638*3117ece4Schristos payload = &cparams; 639*3117ece4Schristos break; 640*3117ece4Schristos 641*3117ece4Schristos case 52 : 642*3117ece4Schristos /* compressStream2, short dstCapacity */ 643*3117ece4Schristos dstBuffSize--; 644*3117ece4Schristos break; 645*3117ece4Schristos 646*3117ece4Schristos /* test functions */ 647*3117ece4Schristos /* convention: test functions have ID > 100 */ 648*3117ece4Schristos 649*3117ece4Schristos default : ; 650*3117ece4Schristos } 651*3117ece4Schristos 652*3117ece4Schristos /* warming up dstBuff */ 653*3117ece4Schristos { size_t i; for (i=0; i<dstBuffSize; i++) dstBuff[i]=(BYTE)i; } 654*3117ece4Schristos 655*3117ece4Schristos /* benchmark loop */ 656*3117ece4Schristos { BMK_timedFnState_t* const tfs = BMK_createTimedFnState(g_nbIterations * 1000, 1000); 657*3117ece4Schristos void* const avoidStrictAliasingPtr = &dstBuff; 658*3117ece4Schristos BMK_benchParams_t bp; 659*3117ece4Schristos BMK_runTime_t bestResult; 660*3117ece4Schristos bestResult.sumOfReturn = 0; 661*3117ece4Schristos bestResult.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */ 662*3117ece4Schristos CONTROL(tfs != NULL); 663*3117ece4Schristos 664*3117ece4Schristos bp.benchFn = benchFunction; 665*3117ece4Schristos bp.benchPayload = payload; 666*3117ece4Schristos bp.initFn = NULL; 667*3117ece4Schristos bp.initPayload = NULL; 668*3117ece4Schristos bp.errorFn = ZSTD_isError; 669*3117ece4Schristos bp.blockCount = 1; 670*3117ece4Schristos bp.srcBuffers = &src; 671*3117ece4Schristos bp.srcSizes = &srcSize; 672*3117ece4Schristos bp.dstBuffers = (void* const*) avoidStrictAliasingPtr; /* circumvent strict aliasing warning on gcc-8, 673*3117ece4Schristos * because gcc considers that `void* const *` and `void**` are 2 different types */ 674*3117ece4Schristos bp.dstCapacities = &dstBuffSize; 675*3117ece4Schristos bp.blockResults = NULL; 676*3117ece4Schristos 677*3117ece4Schristos for (;;) { 678*3117ece4Schristos BMK_runOutcome_t const bOutcome = BMK_benchTimedFn(tfs, bp); 679*3117ece4Schristos 680*3117ece4Schristos if (!BMK_isSuccessful_runOutcome(bOutcome)) { 681*3117ece4Schristos DISPLAY("ERROR benchmarking function ! ! \n"); 682*3117ece4Schristos errorcode = 1; 683*3117ece4Schristos goto _cleanOut; 684*3117ece4Schristos } 685*3117ece4Schristos 686*3117ece4Schristos { BMK_runTime_t const newResult = BMK_extract_runTime(bOutcome); 687*3117ece4Schristos if (newResult.nanoSecPerRun < bestResult.nanoSecPerRun ) 688*3117ece4Schristos bestResult.nanoSecPerRun = newResult.nanoSecPerRun; 689*3117ece4Schristos DISPLAY("\r%2u#%-29.29s:%8.1f MB/s (%8u) ", 690*3117ece4Schristos benchNb, benchName, 691*3117ece4Schristos (double)srcSize * TIMELOOP_NANOSEC / bestResult.nanoSecPerRun / MB_UNIT, 692*3117ece4Schristos (unsigned)newResult.sumOfReturn ); 693*3117ece4Schristos } 694*3117ece4Schristos 695*3117ece4Schristos if ( BMK_isCompleted_TimedFn(tfs) ) break; 696*3117ece4Schristos } 697*3117ece4Schristos BMK_freeTimedFnState(tfs); 698*3117ece4Schristos } 699*3117ece4Schristos DISPLAY("\n"); 700*3117ece4Schristos 701*3117ece4Schristos _cleanOut: 702*3117ece4Schristos free(dstBuff); 703*3117ece4Schristos free(dstBuff2); 704*3117ece4Schristos ZSTD_freeCCtx(g_zcc); g_zcc=NULL; 705*3117ece4Schristos ZSTD_freeDCtx(g_zdc); g_zdc=NULL; 706*3117ece4Schristos ZSTD_freeCStream(g_cstream); g_cstream=NULL; 707*3117ece4Schristos ZSTD_freeDStream(g_dstream); g_dstream=NULL; 708*3117ece4Schristos return errorcode; 709*3117ece4Schristos } 710*3117ece4Schristos 711*3117ece4Schristos 712*3117ece4Schristos static int benchSample(U32 benchNb, 713*3117ece4Schristos size_t benchedSize, double compressibility, 714*3117ece4Schristos int cLevel, ZSTD_compressionParameters cparams) 715*3117ece4Schristos { 716*3117ece4Schristos /* Allocation */ 717*3117ece4Schristos void* const origBuff = malloc(benchedSize); 718*3117ece4Schristos if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); return 12; } 719*3117ece4Schristos 720*3117ece4Schristos /* Fill buffer */ 721*3117ece4Schristos RDG_genBuffer(origBuff, benchedSize, compressibility, 0.0, 0); 722*3117ece4Schristos 723*3117ece4Schristos /* bench */ 724*3117ece4Schristos DISPLAY("\r%70s\r", ""); 725*3117ece4Schristos DISPLAY(" Sample %u bytes : \n", (unsigned)benchedSize); 726*3117ece4Schristos if (benchNb) { 727*3117ece4Schristos benchMem(benchNb, origBuff, benchedSize, cLevel, cparams); 728*3117ece4Schristos } else { /* 0 == run all tests */ 729*3117ece4Schristos for (benchNb=0; benchNb<100; benchNb++) { 730*3117ece4Schristos benchMem(benchNb, origBuff, benchedSize, cLevel, cparams); 731*3117ece4Schristos } } 732*3117ece4Schristos 733*3117ece4Schristos free(origBuff); 734*3117ece4Schristos return 0; 735*3117ece4Schristos } 736*3117ece4Schristos 737*3117ece4Schristos 738*3117ece4Schristos static int benchFiles(U32 benchNb, 739*3117ece4Schristos const char** fileNamesTable, const int nbFiles, 740*3117ece4Schristos int cLevel, ZSTD_compressionParameters cparams) 741*3117ece4Schristos { 742*3117ece4Schristos /* Loop for each file */ 743*3117ece4Schristos int fileIdx; 744*3117ece4Schristos for (fileIdx=0; fileIdx<nbFiles; fileIdx++) { 745*3117ece4Schristos const char* const inFileName = fileNamesTable[fileIdx]; 746*3117ece4Schristos FILE* const inFile = fopen( inFileName, "rb" ); 747*3117ece4Schristos size_t benchedSize; 748*3117ece4Schristos 749*3117ece4Schristos /* Check file existence */ 750*3117ece4Schristos if (inFile==NULL) { DISPLAY( "Pb opening %s\n", inFileName); return 11; } 751*3117ece4Schristos 752*3117ece4Schristos /* Memory allocation & restrictions */ 753*3117ece4Schristos { U64 const inFileSize = UTIL_getFileSize(inFileName); 754*3117ece4Schristos if (inFileSize == UTIL_FILESIZE_UNKNOWN) { 755*3117ece4Schristos DISPLAY( "Cannot measure size of %s\n", inFileName); 756*3117ece4Schristos fclose(inFile); 757*3117ece4Schristos return 11; 758*3117ece4Schristos } 759*3117ece4Schristos benchedSize = BMK_findMaxMem(inFileSize*3) / 3; 760*3117ece4Schristos if ((U64)benchedSize > inFileSize) 761*3117ece4Schristos benchedSize = (size_t)inFileSize; 762*3117ece4Schristos if ((U64)benchedSize < inFileSize) { 763*3117ece4Schristos DISPLAY("Not enough memory for '%s' full size; testing %u MB only... \n", 764*3117ece4Schristos inFileName, (unsigned)(benchedSize>>20)); 765*3117ece4Schristos } } 766*3117ece4Schristos 767*3117ece4Schristos /* Alloc */ 768*3117ece4Schristos { void* const origBuff = malloc(benchedSize); 769*3117ece4Schristos if (!origBuff) { DISPLAY("\nError: not enough memory!\n"); fclose(inFile); return 12; } 770*3117ece4Schristos 771*3117ece4Schristos /* Fill input buffer */ 772*3117ece4Schristos DISPLAY("Loading %s... \r", inFileName); 773*3117ece4Schristos { size_t const readSize = fread(origBuff, 1, benchedSize, inFile); 774*3117ece4Schristos fclose(inFile); 775*3117ece4Schristos if (readSize != benchedSize) { 776*3117ece4Schristos DISPLAY("\nError: problem reading file '%s' !! \n", inFileName); 777*3117ece4Schristos free(origBuff); 778*3117ece4Schristos return 13; 779*3117ece4Schristos } } 780*3117ece4Schristos 781*3117ece4Schristos /* bench */ 782*3117ece4Schristos DISPLAY("\r%70s\r", ""); /* blank line */ 783*3117ece4Schristos DISPLAY(" %s : \n", inFileName); 784*3117ece4Schristos if (benchNb) { 785*3117ece4Schristos benchMem(benchNb, origBuff, benchedSize, cLevel, cparams); 786*3117ece4Schristos } else { 787*3117ece4Schristos for (benchNb=0; benchNb<100; benchNb++) { 788*3117ece4Schristos benchMem(benchNb, origBuff, benchedSize, cLevel, cparams); 789*3117ece4Schristos } 790*3117ece4Schristos benchNb = 0; 791*3117ece4Schristos } 792*3117ece4Schristos 793*3117ece4Schristos free(origBuff); 794*3117ece4Schristos } } 795*3117ece4Schristos 796*3117ece4Schristos return 0; 797*3117ece4Schristos } 798*3117ece4Schristos 799*3117ece4Schristos 800*3117ece4Schristos 801*3117ece4Schristos /*_******************************************************* 802*3117ece4Schristos * Argument Parsing 803*3117ece4Schristos *********************************************************/ 804*3117ece4Schristos 805*3117ece4Schristos #define ERROR_OUT(msg) { DISPLAY("%s \n", msg); exit(1); } 806*3117ece4Schristos 807*3117ece4Schristos static unsigned readU32FromChar(const char** stringPtr) 808*3117ece4Schristos { 809*3117ece4Schristos const char errorMsg[] = "error: numeric value too large"; 810*3117ece4Schristos unsigned result = 0; 811*3117ece4Schristos while ((**stringPtr >='0') && (**stringPtr <='9')) { 812*3117ece4Schristos unsigned const max = (((unsigned)(-1)) / 10) - 1; 813*3117ece4Schristos if (result > max) ERROR_OUT(errorMsg); 814*3117ece4Schristos result *= 10; 815*3117ece4Schristos result += (unsigned)(**stringPtr - '0'); 816*3117ece4Schristos (*stringPtr)++ ; 817*3117ece4Schristos } 818*3117ece4Schristos if ((**stringPtr=='K') || (**stringPtr=='M')) { 819*3117ece4Schristos unsigned const maxK = ((unsigned)(-1)) >> 10; 820*3117ece4Schristos if (result > maxK) ERROR_OUT(errorMsg); 821*3117ece4Schristos result <<= 10; 822*3117ece4Schristos if (**stringPtr=='M') { 823*3117ece4Schristos if (result > maxK) ERROR_OUT(errorMsg); 824*3117ece4Schristos result <<= 10; 825*3117ece4Schristos } 826*3117ece4Schristos (*stringPtr)++; /* skip `K` or `M` */ 827*3117ece4Schristos if (**stringPtr=='i') (*stringPtr)++; 828*3117ece4Schristos if (**stringPtr=='B') (*stringPtr)++; 829*3117ece4Schristos } 830*3117ece4Schristos return result; 831*3117ece4Schristos } 832*3117ece4Schristos 833*3117ece4Schristos static int longCommandWArg(const char** stringPtr, const char* longCommand) 834*3117ece4Schristos { 835*3117ece4Schristos size_t const comSize = strlen(longCommand); 836*3117ece4Schristos int const result = !strncmp(*stringPtr, longCommand, comSize); 837*3117ece4Schristos if (result) *stringPtr += comSize; 838*3117ece4Schristos return result; 839*3117ece4Schristos } 840*3117ece4Schristos 841*3117ece4Schristos 842*3117ece4Schristos /*_******************************************************* 843*3117ece4Schristos * Command line 844*3117ece4Schristos *********************************************************/ 845*3117ece4Schristos 846*3117ece4Schristos static int usage(const char* exename) 847*3117ece4Schristos { 848*3117ece4Schristos DISPLAY( "Usage :\n"); 849*3117ece4Schristos DISPLAY( " %s [arg] file1 file2 ... fileX\n", exename); 850*3117ece4Schristos DISPLAY( "Arguments :\n"); 851*3117ece4Schristos DISPLAY( " -H/-h : Help (this text + advanced options)\n"); 852*3117ece4Schristos return 0; 853*3117ece4Schristos } 854*3117ece4Schristos 855*3117ece4Schristos static int usage_advanced(const char* exename) 856*3117ece4Schristos { 857*3117ece4Schristos usage(exename); 858*3117ece4Schristos DISPLAY( "\nAdvanced options :\n"); 859*3117ece4Schristos DISPLAY( " -b# : test only function # \n"); 860*3117ece4Schristos DISPLAY( " -l# : benchmark functions at that compression level (default : %i)\n", DEFAULT_CLEVEL); 861*3117ece4Schristos DISPLAY( "--zstd= : custom parameter selection. Format same as zstdcli \n"); 862*3117ece4Schristos DISPLAY( " -P# : sample compressibility (default : %.1f%%)\n", COMPRESSIBILITY_DEFAULT * 100); 863*3117ece4Schristos DISPLAY( " -B# : sample size (default : %u)\n", (unsigned)kSampleSizeDefault); 864*3117ece4Schristos DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS); 865*3117ece4Schristos return 0; 866*3117ece4Schristos } 867*3117ece4Schristos 868*3117ece4Schristos static int badusage(const char* exename) 869*3117ece4Schristos { 870*3117ece4Schristos DISPLAY("Wrong parameters\n"); 871*3117ece4Schristos usage(exename); 872*3117ece4Schristos return 1; 873*3117ece4Schristos } 874*3117ece4Schristos 875*3117ece4Schristos int main(int argc, const char** argv) 876*3117ece4Schristos { 877*3117ece4Schristos int argNb, filenamesStart=0, result; 878*3117ece4Schristos const char* const exename = argv[0]; 879*3117ece4Schristos const char* input_filename = NULL; 880*3117ece4Schristos U32 benchNb = 0, main_pause = 0; 881*3117ece4Schristos int cLevel = DEFAULT_CLEVEL; 882*3117ece4Schristos ZSTD_compressionParameters cparams = ZSTD_getCParams(cLevel, 0, 0); 883*3117ece4Schristos size_t sampleSize = kSampleSizeDefault; 884*3117ece4Schristos double compressibility = COMPRESSIBILITY_DEFAULT; 885*3117ece4Schristos 886*3117ece4Schristos DISPLAY(WELCOME_MESSAGE); 887*3117ece4Schristos if (argc<1) return badusage(exename); 888*3117ece4Schristos 889*3117ece4Schristos for (argNb=1; argNb<argc; argNb++) { 890*3117ece4Schristos const char* argument = argv[argNb]; 891*3117ece4Schristos CONTROL(argument != NULL); 892*3117ece4Schristos 893*3117ece4Schristos if (longCommandWArg(&argument, "--zstd=")) { 894*3117ece4Schristos for ( ; ;) { 895*3117ece4Schristos if (longCommandWArg(&argument, "windowLog=") || longCommandWArg(&argument, "wlog=")) { cparams.windowLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 896*3117ece4Schristos if (longCommandWArg(&argument, "chainLog=") || longCommandWArg(&argument, "clog=")) { cparams.chainLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 897*3117ece4Schristos if (longCommandWArg(&argument, "hashLog=") || longCommandWArg(&argument, "hlog=")) { cparams.hashLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 898*3117ece4Schristos if (longCommandWArg(&argument, "searchLog=") || longCommandWArg(&argument, "slog=")) { cparams.searchLog = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 899*3117ece4Schristos if (longCommandWArg(&argument, "minMatch=") || longCommandWArg(&argument, "mml=")) { cparams.minMatch = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 900*3117ece4Schristos if (longCommandWArg(&argument, "targetLength=") || longCommandWArg(&argument, "tlen=")) { cparams.targetLength = readU32FromChar(&argument); if (argument[0]==',') { argument++; continue; } else break; } 901*3117ece4Schristos if (longCommandWArg(&argument, "strategy=") || longCommandWArg(&argument, "strat=")) { cparams.strategy = (ZSTD_strategy)(readU32FromChar(&argument)); if (argument[0]==',') { argument++; continue; } else break; } 902*3117ece4Schristos if (longCommandWArg(&argument, "level=") || longCommandWArg(&argument, "lvl=")) { cLevel = (int)readU32FromChar(&argument); cparams = ZSTD_getCParams(cLevel, 0, 0); if (argument[0]==',') { argument++; continue; } else break; } 903*3117ece4Schristos DISPLAY("invalid compression parameter \n"); 904*3117ece4Schristos return 1; 905*3117ece4Schristos } 906*3117ece4Schristos 907*3117ece4Schristos /* check end of string */ 908*3117ece4Schristos if (argument[0] != 0) { 909*3117ece4Schristos DISPLAY("invalid --zstd= format \n"); 910*3117ece4Schristos return 1; 911*3117ece4Schristos } else { 912*3117ece4Schristos continue; 913*3117ece4Schristos } 914*3117ece4Schristos 915*3117ece4Schristos } else if (argument[0]=='-') { /* Commands (note : aggregated commands are allowed) */ 916*3117ece4Schristos argument++; 917*3117ece4Schristos while (argument[0]!=0) { 918*3117ece4Schristos 919*3117ece4Schristos switch(argument[0]) 920*3117ece4Schristos { 921*3117ece4Schristos /* Display help on usage */ 922*3117ece4Schristos case 'h': 923*3117ece4Schristos case 'H': return usage_advanced(exename); 924*3117ece4Schristos 925*3117ece4Schristos /* Pause at the end (hidden option) */ 926*3117ece4Schristos case 'p': main_pause = 1; break; 927*3117ece4Schristos 928*3117ece4Schristos /* Select specific algorithm to bench */ 929*3117ece4Schristos case 'b': 930*3117ece4Schristos argument++; 931*3117ece4Schristos benchNb = readU32FromChar(&argument); 932*3117ece4Schristos break; 933*3117ece4Schristos 934*3117ece4Schristos /* Select compression level to use */ 935*3117ece4Schristos case 'l': 936*3117ece4Schristos argument++; 937*3117ece4Schristos cLevel = (int)readU32FromChar(&argument); 938*3117ece4Schristos cparams = ZSTD_getCParams(cLevel, 0, 0); 939*3117ece4Schristos break; 940*3117ece4Schristos 941*3117ece4Schristos /* Select compressibility of synthetic sample */ 942*3117ece4Schristos case 'P': 943*3117ece4Schristos argument++; 944*3117ece4Schristos compressibility = (double)readU32FromChar(&argument) / 100.; 945*3117ece4Schristos break; 946*3117ece4Schristos 947*3117ece4Schristos /* Select size of synthetic sample */ 948*3117ece4Schristos case 'B': 949*3117ece4Schristos argument++; 950*3117ece4Schristos sampleSize = (size_t)readU32FromChar(&argument); 951*3117ece4Schristos break; 952*3117ece4Schristos 953*3117ece4Schristos /* Modify Nb Iterations */ 954*3117ece4Schristos case 'i': 955*3117ece4Schristos argument++; 956*3117ece4Schristos g_nbIterations = readU32FromChar(&argument); 957*3117ece4Schristos break; 958*3117ece4Schristos 959*3117ece4Schristos /* Unknown command */ 960*3117ece4Schristos default : return badusage(exename); 961*3117ece4Schristos } 962*3117ece4Schristos } 963*3117ece4Schristos continue; 964*3117ece4Schristos } 965*3117ece4Schristos 966*3117ece4Schristos /* first provided filename is input */ 967*3117ece4Schristos if (!input_filename) { input_filename=argument; filenamesStart=argNb; continue; } 968*3117ece4Schristos } 969*3117ece4Schristos 970*3117ece4Schristos 971*3117ece4Schristos 972*3117ece4Schristos if (filenamesStart==0) /* no input file */ 973*3117ece4Schristos result = benchSample(benchNb, sampleSize, compressibility, cLevel, cparams); 974*3117ece4Schristos else 975*3117ece4Schristos result = benchFiles(benchNb, argv+filenamesStart, argc-filenamesStart, cLevel, cparams); 976*3117ece4Schristos 977*3117ece4Schristos if (main_pause) { int unused; printf("press enter...\n"); unused = getchar(); (void)unused; } 978*3117ece4Schristos 979*3117ece4Schristos return result; 980*3117ece4Schristos } 981