2016-08-30 10:04:33 -07:00
/**
* Copyright ( c ) 2016 - present , Yann Collet , Facebook , Inc .
* All rights reserved .
*
* This source code is licensed under the BSD - style license found in the
* LICENSE file in the root directory of this source tree . An additional grant
* of patent rights can be found in the PATENTS file in the same directory .
*/
2015-01-23 16:58:16 -08:00
2016-03-15 12:47:23 -07:00
/*_************************************
2015-01-23 16:58:16 -08:00
* Includes
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-05-05 04:58:56 -07:00
# include "util.h" /* Compiler options, UTIL_GetFileSize */
# include <stdlib.h> /* malloc */
# include <stdio.h> /* fprintf, fopen, ftello64 */
# include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
2015-01-23 16:58:16 -08:00
2015-10-18 14:18:32 -07:00
# include "mem.h"
2016-07-23 07:31:49 -07:00
# include "zstd_internal.h" /* ZSTD_blockHeaderSize, blockType_e, KB, MB */
2016-06-04 15:58:01 -07:00
# define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressBegin, ZSTD_compressContinue, etc. */
2016-07-23 07:31:49 -07:00
# include "zstd.h" /* ZSTD_VERSION_STRING */
2016-06-04 15:58:01 -07:00
# define FSE_STATIC_LINKING_ONLY /* FSE_DTABLE_SIZE_U32 */
# include "fse.h"
2016-03-15 12:47:23 -07:00
# include "zbuff.h"
2015-02-10 09:15:20 -08:00
# include "datagen.h"
2015-01-23 16:58:16 -08:00
2016-03-15 12:47:23 -07:00
/*_************************************
2015-01-23 16:58:16 -08:00
* Constants
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-10-25 16:06:36 -07:00
# define PROGRAM_DESCRIPTION "Zstandard speed analyzer"
2015-01-23 16:58:16 -08:00
# define AUTHOR "Yann Collet"
2016-05-20 03:34:40 -07:00
# define WELCOME_MESSAGE "*** %s %s %i-bits, by %s (%s) ***\n", PROGRAM_DESCRIPTION, ZSTD_VERSION_STRING, (int)(sizeof(void*)*8), AUTHOR, __DATE__
2015-01-23 16:58:16 -08:00
# define NBLOOPS 6
2016-03-17 08:18:36 -07:00
# define TIMELOOP_S 2
2015-01-23 16:58:16 -08:00
# define KNUTH 2654435761U
# define MAX_MEM (1984 MB)
2015-02-10 23:34:50 -08:00
# define COMPRESSIBILITY_DEFAULT 0.50
2016-03-16 07:26:51 -07:00
static const size_t g_sampleSize = 10000000 ;
2015-01-23 16:58:16 -08:00
2016-03-15 12:47:23 -07:00
/*_************************************
2015-01-23 16:58:16 -08:00
* Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
2016-03-15 12:47:23 -07:00
/*_************************************
2015-01-23 16:58:16 -08:00
* Benchmark Parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-17 11:37:33 -07:00
static U32 g_nbIterations = NBLOOPS ;
2015-02-10 23:34:50 -08:00
static double g_compressibility = COMPRESSIBILITY_DEFAULT ;
2015-01-23 16:58:16 -08:00
2016-03-17 11:37:33 -07:00
static void BMK_SetNbIterations ( U32 nbLoops )
2015-01-23 16:58:16 -08:00
{
2016-03-17 11:37:33 -07:00
g_nbIterations = nbLoops ;
DISPLAY ( " - %i iterations - \n " , g_nbIterations ) ;
2015-01-23 16:58:16 -08:00
}
2016-03-15 12:47:23 -07:00
/*_*******************************************************
2015-01-23 16:58:16 -08:00
* Private functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-17 08:18:36 -07:00
static clock_t BMK_clockSpan ( clock_t clockStart )
2015-01-23 16:58:16 -08:00
{
2016-03-17 11:37:33 -07:00
return clock ( ) - clockStart ; /* works even if overflow, span limited to <= ~30mn */
2015-01-23 16:58:16 -08:00
}
static size_t BMK_findMaxMem ( U64 requiredMem )
{
2016-03-25 12:29:35 -07:00
size_t const step = 64 MB ;
2016-03-15 12:47:23 -07:00
void * testmem = NULL ;
2015-01-23 16:58:16 -08:00
requiredMem = ( ( ( requiredMem > > 26 ) + 1 ) < < 26 ) ;
if ( requiredMem > MAX_MEM ) requiredMem = MAX_MEM ;
2016-03-17 11:37:33 -07:00
requiredMem + = step ;
do {
2016-03-15 12:47:23 -07:00
testmem = malloc ( ( size_t ) requiredMem ) ;
2015-01-23 16:58:16 -08:00
requiredMem - = step ;
2016-03-17 11:37:33 -07:00
} while ( ! testmem ) ;
2015-01-23 16:58:16 -08:00
free ( testmem ) ;
2016-03-17 11:37:33 -07:00
return ( size_t ) requiredMem ;
2015-01-23 16:58:16 -08:00
}
2016-03-15 12:47:23 -07:00
/*_*******************************************************
2015-01-23 16:58:16 -08:00
* Benchmark wrappers
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-15 12:47:23 -07:00
typedef struct {
2016-07-23 07:31:49 -07:00
blockType_e blockType ;
2015-01-23 16:58:16 -08:00
U32 unusedBits ;
U32 origSize ;
} blockProperties_t ;
size_t local_ZSTD_compress ( void * dst , size_t dstSize , void * buff2 , const void * src , size_t srcSize )
{
( void ) buff2 ;
2015-11-11 04:43:58 -08:00
return ZSTD_compress ( dst , dstSize , src , srcSize , 1 ) ;
2015-01-23 16:58:16 -08:00
}
2016-03-16 08:05:18 -07:00
static size_t g_cSize = 0 ;
2015-01-23 16:58:16 -08:00
size_t local_ZSTD_decompress ( void * dst , size_t dstSize , void * buff2 , const void * src , size_t srcSize )
{
( void ) src ; ( void ) srcSize ;
return ZSTD_decompress ( dst , dstSize , buff2 , g_cSize ) ;
}
2016-03-16 08:05:18 -07:00
static ZSTD_DCtx * g_zdc = NULL ;
2015-11-12 07:00:04 -08:00
extern size_t ZSTD_decodeLiteralsBlock ( ZSTD_DCtx * ctx , const void * src , size_t srcSize ) ;
2015-01-23 16:58:16 -08:00
size_t local_ZSTD_decodeLiteralsBlock ( void * dst , size_t dstSize , void * buff2 , const void * src , size_t srcSize )
{
2015-10-18 14:18:32 -07:00
( void ) src ; ( void ) srcSize ; ( void ) dst ; ( void ) dstSize ;
2016-03-16 08:05:18 -07:00
return ZSTD_decodeLiteralsBlock ( ( ZSTD_DCtx * ) g_zdc , buff2 , g_cSize ) ;
2015-01-23 16:58:16 -08:00
}
2016-03-15 12:47:23 -07:00
extern size_t ZSTD_getcBlockSize ( const void * src , size_t srcSize , blockProperties_t * bpPtr ) ;
2016-04-09 08:38:53 -07:00
extern size_t ZSTD_decodeSeqHeaders ( int * nbSeq , FSE_DTable * DTableLL , FSE_DTable * DTableML , FSE_DTable * DTableOffb , U32 tableRepeatFlag , const void * src , size_t srcSize ) ;
2015-01-23 16:58:16 -08:00
size_t local_ZSTD_decodeSeqHeaders ( void * dst , size_t dstSize , void * buff2 , const void * src , size_t srcSize )
{
2015-12-10 06:51:38 -08:00
U32 DTableML [ FSE_DTABLE_SIZE_U32 ( 10 ) ] , DTableLL [ FSE_DTABLE_SIZE_U32 ( 10 ) ] , DTableOffb [ FSE_DTABLE_SIZE_U32 ( 9 ) ] ; /* MLFSELog, LLFSELog and OffFSELog are not public values */
2015-08-19 16:02:43 -07:00
int nbSeq ;
2015-01-23 16:58:16 -08:00
( void ) src ; ( void ) srcSize ; ( void ) dst ; ( void ) dstSize ;
2016-04-09 08:38:53 -07:00
return ZSTD_decodeSeqHeaders ( & nbSeq , DTableLL , DTableML , DTableOffb , 0 , buff2 , g_cSize ) ;
2015-01-23 16:58:16 -08:00
}
2016-03-15 12:47:23 -07:00
static ZBUFF_CCtx * g_zbcc = NULL ;
2016-03-16 08:05:18 -07:00
size_t local_ZBUFF_compress ( void * dst , size_t dstCapacity , void * buff2 , const void * src , size_t srcSize )
2016-03-15 12:47:23 -07:00
{
size_t compressedSize ;
2016-03-16 08:05:18 -07:00
size_t srcRead = srcSize , dstWritten = dstCapacity ;
2016-03-15 12:47:23 -07:00
( void ) buff2 ;
ZBUFF_compressInit ( g_zbcc , 1 ) ;
ZBUFF_compressContinue ( g_zbcc , dst , & dstWritten , src , & srcRead ) ;
compressedSize = dstWritten ;
2016-03-16 08:05:18 -07:00
dstWritten = dstCapacity - compressedSize ;
2016-03-15 12:47:23 -07:00
ZBUFF_compressEnd ( g_zbcc , ( ( char * ) dst ) + compressedSize , & dstWritten ) ;
compressedSize + = dstWritten ;
return compressedSize ;
}
static ZBUFF_DCtx * g_zbdc = NULL ;
2016-03-16 08:05:18 -07:00
static size_t local_ZBUFF_decompress ( void * dst , size_t dstCapacity , void * buff2 , const void * src , size_t srcSize )
2016-03-15 12:47:23 -07:00
{
2016-03-16 08:05:18 -07:00
size_t srcRead = g_cSize , dstWritten = dstCapacity ;
2016-03-15 12:47:23 -07:00
( void ) src ; ( void ) srcSize ;
ZBUFF_decompressInit ( g_zbdc ) ;
ZBUFF_decompressContinue ( g_zbdc , dst , & dstWritten , buff2 , & srcRead ) ;
return dstWritten ;
}
2016-03-16 08:05:18 -07:00
static ZSTD_CCtx * g_zcc = NULL ;
size_t local_ZSTD_compressContinue ( void * dst , size_t dstCapacity , void * buff2 , const void * src , size_t srcSize )
{
( void ) buff2 ;
ZSTD_compressBegin ( g_zcc , 1 ) ;
2016-07-28 06:29:08 -07:00
return ZSTD_compressEnd ( g_zcc , dst , dstCapacity , src , srcSize ) ;
2016-03-16 08:05:18 -07:00
}
size_t local_ZSTD_decompressContinue ( void * dst , size_t dstCapacity , void * buff2 , const void * src , size_t srcSize )
{
size_t regeneratedSize = 0 ;
const BYTE * ip = ( const BYTE * ) buff2 ;
const BYTE * const iend = ip + g_cSize ;
BYTE * op = ( BYTE * ) dst ;
size_t remainingCapacity = dstCapacity ;
( void ) src ; ( void ) srcSize ;
ZSTD_decompressBegin ( g_zdc ) ;
while ( ip < iend ) {
size_t const iSize = ZSTD_nextSrcSizeToDecompress ( g_zdc ) ;
size_t const decodedSize = ZSTD_decompressContinue ( g_zdc , op , remainingCapacity , ip , iSize ) ;
ip + = iSize ;
regeneratedSize + = decodedSize ;
op + = decodedSize ;
remainingCapacity - = decodedSize ;
}
return regeneratedSize ;
}
2015-01-23 16:58:16 -08:00
2016-03-15 12:47:23 -07:00
/*_*******************************************************
2015-01-23 16:58:16 -08:00
* Bench functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-16 07:26:51 -07:00
static size_t benchMem ( const void * src , size_t srcSize , U32 benchNb )
2015-01-23 16:58:16 -08:00
{
BYTE * dstBuff ;
2016-07-23 07:31:49 -07:00
size_t const dstBuffSize = ZSTD_compressBound ( srcSize ) ;
void * buff2 ;
2015-01-23 16:58:16 -08:00
const char * benchName ;
size_t ( * benchFunction ) ( void * dst , size_t dstSize , void * verifBuff , const void * src , size_t srcSize ) ;
double bestTime = 100000000. ;
2015-02-10 09:15:20 -08:00
/* Selection */
2015-01-23 16:58:16 -08:00
switch ( benchNb )
{
case 1 :
benchFunction = local_ZSTD_compress ; benchName = " ZSTD_compress " ;
break ;
2016-03-15 13:13:52 -07:00
case 2 :
2015-01-23 16:58:16 -08:00
benchFunction = local_ZSTD_decompress ; benchName = " ZSTD_decompress " ;
break ;
2016-03-16 08:05:18 -07:00
case 11 :
benchFunction = local_ZSTD_compressContinue ; benchName = " ZSTD_compressContinue " ;
break ;
case 12 :
benchFunction = local_ZSTD_decompressContinue ; benchName = " ZSTD_decompressContinue " ;
break ;
2015-01-23 16:58:16 -08:00
case 31 :
benchFunction = local_ZSTD_decodeLiteralsBlock ; benchName = " ZSTD_decodeLiteralsBlock " ;
break ;
case 32 :
benchFunction = local_ZSTD_decodeSeqHeaders ; benchName = " ZSTD_decodeSeqHeaders " ;
break ;
2016-03-15 12:47:23 -07:00
case 41 :
benchFunction = local_ZBUFF_compress ; benchName = " ZBUFF_compressContinue " ;
break ;
case 42 :
benchFunction = local_ZBUFF_decompress ; benchName = " ZBUFF_decompressContinue " ;
break ;
2015-01-23 16:58:16 -08:00
default :
return 0 ;
}
/* Allocation */
2015-06-18 08:43:16 -07:00
dstBuff = ( BYTE * ) malloc ( dstBuffSize ) ;
2016-07-23 07:31:49 -07:00
buff2 = malloc ( dstBuffSize ) ;
2016-03-15 12:47:23 -07:00
if ( ( ! dstBuff ) | | ( ! buff2 ) ) {
2015-01-23 16:58:16 -08:00
DISPLAY ( " \n Error: not enough memory! \n " ) ;
free ( dstBuff ) ; free ( buff2 ) ;
return 12 ;
}
/* Preparation */
switch ( benchNb )
{
2016-03-15 13:13:52 -07:00
case 2 :
2015-11-11 04:43:58 -08:00
g_cSize = ZSTD_compress ( buff2 , dstBuffSize , src , srcSize , 1 ) ;
2015-01-23 16:58:16 -08:00
break ;
2016-03-16 08:05:18 -07:00
case 11 :
if ( g_zcc = = NULL ) g_zcc = ZSTD_createCCtx ( ) ;
break ;
case 12 :
if ( g_zdc = = NULL ) g_zdc = ZSTD_createDCtx ( ) ;
2015-11-11 04:43:58 -08:00
g_cSize = ZSTD_compress ( buff2 , dstBuffSize , src , srcSize , 1 ) ;
2015-01-23 16:58:16 -08:00
break ;
2015-02-10 09:15:20 -08:00
case 31 : /* ZSTD_decodeLiteralsBlock */
2016-03-17 08:42:16 -07:00
if ( g_zdc = = NULL ) g_zdc = ZSTD_createDCtx ( ) ;
2016-03-16 08:05:18 -07:00
{ blockProperties_t bp ;
2016-03-17 08:42:16 -07:00
ZSTD_frameParams zfp ;
size_t frameHeaderSize , skippedSize ;
2015-11-11 04:43:58 -08:00
g_cSize = ZSTD_compress ( dstBuff , dstBuffSize , src , srcSize , 1 ) ;
2016-03-17 08:42:16 -07:00
frameHeaderSize = ZSTD_getFrameParams ( & zfp , dstBuff , ZSTD_frameHeaderSize_min ) ;
if ( frameHeaderSize = = 0 ) frameHeaderSize = ZSTD_frameHeaderSize_min ;
ZSTD_getcBlockSize ( dstBuff + frameHeaderSize , dstBuffSize , & bp ) ; /* Get 1st block type */
2016-03-15 12:47:23 -07:00
if ( bp . blockType ! = bt_compressed ) {
2015-01-24 04:31:55 -08:00
DISPLAY ( " ZSTD_decodeLiteralsBlock : impossible to test on this sample (not compressible) \n " ) ;
2015-11-13 06:08:43 -08:00
goto _cleanOut ;
2015-01-24 04:31:55 -08:00
}
2016-07-23 07:31:49 -07:00
skippedSize = frameHeaderSize + ZSTD_blockHeaderSize ;
2016-03-17 08:42:16 -07:00
memcpy ( buff2 , dstBuff + skippedSize , g_cSize - skippedSize ) ;
2015-11-25 05:42:45 -08:00
srcSize = srcSize > 128 KB ? 128 KB : srcSize ; /* speed relative to block */
2015-01-23 16:58:16 -08:00
break ;
}
2015-02-10 09:15:20 -08:00
case 32 : /* ZSTD_decodeSeqHeaders */
2016-03-16 08:05:18 -07:00
if ( g_zdc = = NULL ) g_zdc = ZSTD_createDCtx ( ) ;
{ blockProperties_t bp ;
2016-03-17 08:42:16 -07:00
ZSTD_frameParams zfp ;
2015-01-23 16:58:16 -08:00
const BYTE * ip = dstBuff ;
const BYTE * iend ;
2016-03-17 08:42:16 -07:00
size_t frameHeaderSize , cBlockSize ;
2015-11-25 05:42:45 -08:00
ZSTD_compress ( dstBuff , dstBuffSize , src , srcSize , 1 ) ; /* it would be better to use direct block compression here */
2016-03-17 08:42:16 -07:00
g_cSize = ZSTD_compress ( dstBuff , dstBuffSize , src , srcSize , 1 ) ;
frameHeaderSize = ZSTD_getFrameParams ( & zfp , dstBuff , ZSTD_frameHeaderSize_min ) ;
if ( frameHeaderSize = = 0 ) frameHeaderSize = ZSTD_frameHeaderSize_min ;
ip + = frameHeaderSize ; /* Skip frame Header */
cBlockSize = ZSTD_getcBlockSize ( ip , dstBuffSize , & bp ) ; /* Get 1st block type */
2016-03-15 13:44:39 -07:00
if ( bp . blockType ! = bt_compressed ) {
2015-01-24 04:31:55 -08:00
DISPLAY ( " ZSTD_decodeSeqHeaders : impossible to test on this sample (not compressible) \n " ) ;
2015-11-13 06:08:43 -08:00
goto _cleanOut ;
2015-01-24 04:31:55 -08:00
}
2016-07-23 07:31:49 -07:00
iend = ip + ZSTD_blockHeaderSize + cBlockSize ; /* End of first block */
ip + = ZSTD_blockHeaderSize ; /* skip block header */
ip + = ZSTD_decodeLiteralsBlock ( g_zdc , ip , iend - ip ) ; /* skip literal segment */
2015-01-23 16:58:16 -08:00
g_cSize = iend - ip ;
2015-11-25 05:42:45 -08:00
memcpy ( buff2 , ip , g_cSize ) ; /* copy rest of block (it starts by SeqHeader) */
srcSize = srcSize > 128 KB ? 128 KB : srcSize ; /* speed relative to block */
2015-01-23 16:58:16 -08:00
break ;
}
2016-03-15 12:47:23 -07:00
case 41 :
2016-03-16 08:05:18 -07:00
if ( g_zbcc = = NULL ) g_zbcc = ZBUFF_createCCtx ( ) ;
2016-03-15 12:47:23 -07:00
break ;
case 42 :
2016-03-16 08:05:18 -07:00
if ( g_zbdc = = NULL ) g_zbdc = ZBUFF_createDCtx ( ) ;
2016-03-15 12:47:23 -07:00
g_cSize = ZSTD_compress ( buff2 , dstBuffSize , src , srcSize , 1 ) ;
break ;
2015-01-23 16:58:16 -08:00
/* test functions */
2015-11-25 05:42:45 -08:00
/* by convention, test functions can be added > 100 */
2015-01-23 16:58:16 -08:00
default : ;
}
2015-01-24 04:31:55 -08:00
{ size_t i ; for ( i = 0 ; i < dstBuffSize ; i + + ) dstBuff [ i ] = ( BYTE ) i ; } /* warming up memory */
2016-03-17 11:37:33 -07:00
{ U32 loopNb ;
for ( loopNb = 1 ; loopNb < = g_nbIterations ; loopNb + + ) {
2016-03-17 08:18:36 -07:00
clock_t const timeLoop = TIMELOOP_S * CLOCKS_PER_SEC ;
clock_t clockStart ;
U32 nbRounds ;
size_t benchResult = 0 ;
2015-01-23 16:58:16 -08:00
double averageTime ;
DISPLAY ( " %2i- %-30.30s : \r " , loopNb , benchName ) ;
2016-03-17 08:18:36 -07:00
clockStart = clock ( ) ;
while ( clock ( ) = = clockStart ) ;
clockStart = clock ( ) ;
for ( nbRounds = 0 ; BMK_clockSpan ( clockStart ) < timeLoop ; nbRounds + + ) {
benchResult = benchFunction ( dstBuff , dstBuffSize , buff2 , src , srcSize ) ;
if ( ZSTD_isError ( benchResult ) ) { DISPLAY ( " ERROR ! %s() => %s !! \n " , benchName , ZSTD_getErrorName ( benchResult ) ) ; exit ( 1 ) ; }
2015-01-23 16:58:16 -08:00
}
2016-03-17 08:18:36 -07:00
averageTime = ( ( ( double ) BMK_clockSpan ( clockStart ) ) / CLOCKS_PER_SEC ) / nbRounds ;
2015-01-23 16:58:16 -08:00
if ( averageTime < bestTime ) bestTime = averageTime ;
2016-03-17 08:18:36 -07:00
DISPLAY ( " %2i- %-30.30s : %7.1f MB/s (%9u) \r " , loopNb , benchName , ( double ) srcSize / ( 1 MB ) / bestTime , ( U32 ) benchResult ) ;
2016-03-17 11:37:33 -07:00
} }
2016-03-17 08:18:36 -07:00
DISPLAY ( " %2u \n " , benchNb ) ;
2015-01-23 16:58:16 -08:00
2015-11-13 06:08:43 -08:00
_cleanOut :
2015-01-23 16:58:16 -08:00
free ( dstBuff ) ;
free ( buff2 ) ;
return 0 ;
}
2016-03-16 07:26:51 -07:00
static int benchSample ( U32 benchNb )
2015-01-23 16:58:16 -08:00
{
2016-03-16 07:26:51 -07:00
size_t const benchedSize = g_sampleSize ;
2015-02-10 23:34:50 -08:00
const char * name = " Sample 10MiB " ;
2015-01-23 16:58:16 -08:00
/* Allocation */
2016-03-15 13:44:39 -07:00
void * origBuff = malloc ( benchedSize ) ;
if ( ! origBuff ) { DISPLAY ( " \n Error: not enough memory! \n " ) ; return 12 ; }
2015-01-23 16:58:16 -08:00
/* Fill buffer */
2015-02-10 23:34:50 -08:00
RDG_genBuffer ( origBuff , benchedSize , g_compressibility , 0.0 , 0 ) ;
2015-01-23 16:58:16 -08:00
/* bench */
DISPLAY ( " \r %79s \r " , " " ) ;
DISPLAY ( " %s : \n " , name ) ;
if ( benchNb )
benchMem ( origBuff , benchedSize , benchNb ) ;
else
for ( benchNb = 0 ; benchNb < 100 ; benchNb + + ) benchMem ( origBuff , benchedSize , benchNb ) ;
free ( origBuff ) ;
return 0 ;
}
2016-03-16 07:26:51 -07:00
static int benchFiles ( const char * * fileNamesTable , const int nbFiles , U32 benchNb )
2015-01-23 16:58:16 -08:00
{
/* Loop for each file */
2016-03-16 07:26:51 -07:00
int fileIdx ;
for ( fileIdx = 0 ; fileIdx < nbFiles ; fileIdx + + ) {
const char * inFileName = fileNamesTable [ fileIdx ] ;
2016-03-15 13:44:39 -07:00
FILE * inFile = fopen ( inFileName , " rb " ) ;
2015-01-23 16:58:16 -08:00
U64 inFileSize ;
size_t benchedSize ;
2016-03-15 13:44:39 -07:00
void * origBuff ;
2015-01-23 16:58:16 -08:00
/* Check file existence */
2016-03-15 13:44:39 -07:00
if ( inFile = = NULL ) { DISPLAY ( " Pb opening %s \n " , inFileName ) ; return 11 ; }
2015-01-23 16:58:16 -08:00
2015-12-10 06:51:38 -08:00
/* Memory allocation & restrictions */
2016-04-28 03:23:33 -07:00
inFileSize = UTIL_getFileSize ( inFileName ) ;
2016-03-15 13:44:39 -07:00
benchedSize = BMK_findMaxMem ( inFileSize * 3 ) / 3 ;
2015-01-23 16:58:16 -08:00
if ( ( U64 ) benchedSize > inFileSize ) benchedSize = ( size_t ) inFileSize ;
if ( benchedSize < inFileSize )
2016-03-16 07:26:51 -07:00
DISPLAY ( " Not enough memory for '%s' full size; testing %u MB only... \n " , inFileName , ( U32 ) ( benchedSize > > 20 ) ) ;
2015-01-23 16:58:16 -08:00
2015-01-24 03:08:52 -08:00
/* Alloc */
2016-03-15 13:44:39 -07:00
origBuff = malloc ( benchedSize ) ;
if ( ! origBuff ) { DISPLAY ( " \n Error: not enough memory! \n " ) ; fclose ( inFile ) ; return 12 ; }
2015-01-23 16:58:16 -08:00
2015-01-24 03:08:52 -08:00
/* Fill input buffer */
2015-01-23 16:58:16 -08:00
DISPLAY ( " Loading %s... \r " , inFileName ) ;
{
2016-03-16 07:26:51 -07:00
size_t readSize = fread ( origBuff , 1 , benchedSize , inFile ) ;
fclose ( inFile ) ;
if ( readSize ! = benchedSize ) {
DISPLAY ( " \n Error: problem reading file '%s' !! \n " , inFileName ) ;
free ( origBuff ) ;
return 13 ;
} }
2015-01-23 16:58:16 -08:00
2015-01-24 03:08:52 -08:00
/* bench */
2015-01-23 16:58:16 -08:00
DISPLAY ( " \r %79s \r " , " " ) ;
DISPLAY ( " %s : \n " , inFileName ) ;
if ( benchNb )
benchMem ( origBuff , benchedSize , benchNb ) ;
else
for ( benchNb = 0 ; benchNb < 100 ; benchNb + + ) benchMem ( origBuff , benchedSize , benchNb ) ;
2016-03-16 07:26:51 -07:00
free ( origBuff ) ;
2015-01-23 16:58:16 -08:00
}
return 0 ;
}
2016-03-15 13:44:39 -07:00
static int usage ( const char * exename )
2015-01-23 16:58:16 -08:00
{
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [arg] file1 file2 ... fileX \n " , exename ) ;
DISPLAY ( " Arguments : \n " ) ;
DISPLAY ( " -H/-h : Help (this text + advanced options) \n " ) ;
return 0 ;
}
2016-03-16 07:26:51 -07:00
static int usage_advanced ( const char * exename )
2015-01-23 16:58:16 -08:00
{
2016-03-16 07:26:51 -07:00
usage ( exename ) ;
2015-01-23 16:58:16 -08:00
DISPLAY ( " \n Advanced options : \n " ) ;
DISPLAY ( " -b# : test only function # \n " ) ;
DISPLAY ( " -i# : iteration loops [1-9](default : %i) \n " , NBLOOPS ) ;
2015-02-10 23:34:50 -08:00
DISPLAY ( " -P# : sample compressibility (default : %.1f%%) \n " , COMPRESSIBILITY_DEFAULT * 100 ) ;
2015-01-23 16:58:16 -08:00
return 0 ;
}
2016-03-15 13:44:39 -07:00
static int badusage ( const char * exename )
2015-01-23 16:58:16 -08:00
{
DISPLAY ( " Wrong parameters \n " ) ;
usage ( exename ) ;
2016-03-16 07:26:51 -07:00
return 1 ;
2015-01-23 16:58:16 -08:00
}
2016-03-15 13:44:39 -07:00
int main ( int argc , const char * * argv )
2015-01-23 16:58:16 -08:00
{
2016-03-16 07:26:51 -07:00
int i , filenamesStart = 0 , result ;
const char * exename = argv [ 0 ] ;
const char * input_filename = NULL ;
2015-01-23 16:58:16 -08:00
U32 benchNb = 0 , main_pause = 0 ;
DISPLAY ( WELCOME_MESSAGE ) ;
2016-03-16 07:26:51 -07:00
if ( argc < 1 ) return badusage ( exename ) ;
2015-01-23 16:58:16 -08:00
2016-03-16 07:26:51 -07:00
for ( i = 1 ; i < argc ; i + + ) {
2016-03-15 13:44:39 -07:00
const char * argument = argv [ i ] ;
2016-03-16 07:26:51 -07:00
if ( ! argument ) continue ; /* Protection if argument empty */
2015-01-23 16:58:16 -08:00
2016-03-16 07:26:51 -07:00
/* Commands (note : aggregated commands are allowed) */
if ( argument [ 0 ] = = ' - ' ) {
2015-01-23 16:58:16 -08:00
2016-03-16 07:26:51 -07:00
while ( argument [ 1 ] ! = 0 ) {
argument + + ;
2015-01-23 16:58:16 -08:00
switch ( argument [ 0 ] )
{
2015-02-10 23:34:50 -08:00
/* Display help on usage */
2015-01-23 16:58:16 -08:00
case ' h ' :
2016-03-16 07:26:51 -07:00
case ' H ' : return usage_advanced ( exename ) ;
2015-01-23 16:58:16 -08:00
2015-02-10 23:34:50 -08:00
/* Pause at the end (hidden option) */
2015-01-23 16:58:16 -08:00
case ' p ' : main_pause = 1 ; break ;
2015-02-10 23:34:50 -08:00
/* Select specific algorithm to bench */
2015-01-23 16:58:16 -08:00
case ' b ' :
benchNb = 0 ;
2016-03-15 13:44:39 -07:00
while ( ( argument [ 1 ] > = ' 0 ' ) & & ( argument [ 1 ] < = ' 9 ' ) ) {
2015-01-23 16:58:16 -08:00
benchNb * = 10 ;
benchNb + = argument [ 1 ] - ' 0 ' ;
argument + + ;
}
break ;
2015-02-10 23:34:50 -08:00
/* Modify Nb Iterations */
2015-01-23 16:58:16 -08:00
case ' i ' :
2016-03-15 13:44:39 -07:00
if ( ( argument [ 1 ] > = ' 0 ' ) & & ( argument [ 1 ] < = ' 9 ' ) ) {
2015-01-23 16:58:16 -08:00
int iters = argument [ 1 ] - ' 0 ' ;
BMK_SetNbIterations ( iters ) ;
argument + + ;
}
break ;
2016-03-16 07:26:51 -07:00
/* Select compressibility of synthetic sample */
2015-02-10 23:34:50 -08:00
case ' P ' :
2016-03-15 13:44:39 -07:00
{ U32 proba32 = 0 ;
while ( ( argument [ 1 ] > = ' 0 ' ) & & ( argument [ 1 ] < = ' 9 ' ) ) {
2015-02-10 23:34:50 -08:00
proba32 * = 10 ;
proba32 + = argument [ 1 ] - ' 0 ' ;
argument + + ;
}
g_compressibility = ( double ) proba32 / 100. ;
}
break ;
/* Unknown command */
2016-03-16 07:26:51 -07:00
default : return badusage ( exename ) ;
2015-01-23 16:58:16 -08:00
}
}
continue ;
}
2015-02-10 23:34:50 -08:00
/* first provided filename is input */
2015-01-23 16:58:16 -08:00
if ( ! input_filename ) { input_filename = argument ; filenamesStart = i ; continue ; }
}
2016-03-16 07:26:51 -07:00
if ( filenamesStart = = 0 ) /* no input file */
2015-01-23 16:58:16 -08:00
result = benchSample ( benchNb ) ;
2016-03-16 07:26:51 -07:00
else
result = benchFiles ( argv + filenamesStart , argc - filenamesStart , benchNb ) ;
2015-01-23 16:58:16 -08:00
2015-07-05 00:20:56 -07:00
if ( main_pause ) { int unused ; printf ( " press enter... \n " ) ; unused = getchar ( ) ; ( void ) unused ; }
2015-01-23 16:58:16 -08:00
return result ;
}