Merge pull request #390 from Cyan4973/newBench

Updated benchmark module
This commit is contained in:
Yann Collet 2020-06-15 10:06:54 -07:00 committed by GitHub
commit 4cdfe2f442
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 213 additions and 123 deletions

View File

@ -174,9 +174,13 @@ check: xxhsum ## basic tests for xxhsum CLI, set RUN_ENV for emulated environm
# multiple files
$(RUN_ENV) ./xxhsum$(EXT) xxhash.* xxhsum.*
# internal bench
$(RUN_ENV) ./xxhsum$(EXT) -bi1
$(RUN_ENV) ./xxhsum$(EXT) -bi0
# long bench command
$(RUN_ENV) ./xxhsum$(EXT) --benchmark-all -i0
# bench multiple variants
$(RUN_ENV) ./xxhsum$(EXT) -b1,2,3 -i0
# file bench
$(RUN_ENV) ./xxhsum$(EXT) -bi1 xxhash.c
$(RUN_ENV) ./xxhsum$(EXT) -bi0 xxhash.c
# 32-bit
$(RUN_ENV) ./xxhsum$(EXT) -H0 xxhash.c
# 128-bit
@ -312,7 +316,7 @@ test-inline:
.PHONY: test-all
test-all: CFLAGS += -Werror
test-all: test test32 clangtest cxxtest usan test-inline listL120 trailingWhitespace staticAnalyze test-unicode
test-all: test test32 clangtest cxxtest usan test-inline listL120 trailingWhitespace test-unicode
.PHONY: test-tools
test-tools:

View File

@ -383,6 +383,36 @@ XXHL64_secret_avx512(const void* XXH_RESTRICT input, size_t len, const void* sec
}
#endif
/* === XXH3 update variants === */
XXH_NO_INLINE XXH_errorcode
XXH3_64bits_update_scalar(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_64bits, XXH3_accumulate_512_scalar, XXH3_scrambleAcc_scalar);
}
XXH_NO_INLINE XXH_TARGET_SSE2 XXH_errorcode
XXH3_64bits_update_sse2(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_64bits, XXH3_accumulate_512_sse2, XXH3_scrambleAcc_sse2);
}
XXH_NO_INLINE XXH_TARGET_AVX2 XXH_errorcode
XXH3_64bits_update_avx2(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_64bits, XXH3_accumulate_512_avx2, XXH3_scrambleAcc_avx2);
}
XXH_NO_INLINE XXH_TARGET_AVX512 XXH_errorcode
XXH3_64bits_update_avx512(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_64bits, XXH3_accumulate_512_avx512, XXH3_scrambleAcc_avx512);
}
/* === XXH128 default variants === */
@ -476,6 +506,35 @@ XXHL128_seed_avx512(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t see
}
#endif
/* === XXH128 update variants === */
XXH_NO_INLINE XXH_errorcode
XXH3_128bits_update_scalar(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_128bits, XXH3_accumulate_512_scalar, XXH3_scrambleAcc_scalar);
}
XXH_NO_INLINE XXH_TARGET_SSE2 XXH_errorcode
XXH3_128bits_update_sse2(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_128bits, XXH3_accumulate_512_sse2, XXH3_scrambleAcc_sse2);
}
XXH_NO_INLINE XXH_TARGET_AVX2 XXH_errorcode
XXH3_128bits_update_avx2(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_128bits, XXH3_accumulate_512_avx2, XXH3_scrambleAcc_avx2);
}
XXH_NO_INLINE XXH_TARGET_AVX512 XXH_errorcode
XXH3_128bits_update_avx512(XXH3_state_t* state, const void* input, size_t len)
{
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_128bits, XXH3_accumulate_512_avx512, XXH3_scrambleAcc_avx512);
}
/* ==== Dispatchers ==== */
@ -485,37 +544,23 @@ typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(const void* XXH_RES
typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t);
typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH3_state_t*, const void*, size_t);
typedef struct {
XXH3_dispatchx86_hashLong64_default hashLong64_default;
XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed;
XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret;
XXH3_dispatchx86_update update;
} dispatchFunctions_s;
static dispatchFunctions_s g_dispatch = { NULL, NULL, NULL};
static dispatchFunctions_s g_dispatch = { NULL, NULL, NULL, NULL};
#define NB_DISPATCHES 4
static const dispatchFunctions_s k_dispatch[NB_DISPATCHES] = {
/* scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar },
/* sse2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2 },
/* avx2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2 },
/* avx512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512 }
};
typedef void (*XXH3_dispatchx86_accumulate_512)(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret, XXH3_accWidth_e accWidth);
typedef void (*XXH3_dispatchx86_scrambleAcc)(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret);
typedef struct {
XXH3_dispatchx86_accumulate_512 accumulate_512;
XXH3_dispatchx86_scrambleAcc scrambleAcc;
} coreFunctions_s;
static coreFunctions_s g_coreFunc = { NULL, NULL };
static const coreFunctions_s k_coreFunc[NB_DISPATCHES] = {
/* scalar */ { XXH3_accumulate_512_scalar, XXH3_scrambleAcc_scalar },
/* sse2 */ { XXH3_accumulate_512_sse2, XXH3_scrambleAcc_sse2 },
/* avx2 */ { XXH3_accumulate_512_avx2, XXH3_scrambleAcc_avx2 },
/* avx512 */ { XXH3_accumulate_512_avx512, XXH3_scrambleAcc_avx512 },
/* scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_64bits_update_scalar },
/* sse2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_64bits_update_sse2 },
/* avx2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_64bits_update_avx2 },
/* avx512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_64bits_update_avx512 }
};
typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(const void* XXH_RESTRICT, size_t);
@ -528,15 +573,16 @@ typedef struct {
XXH3_dispatchx86_hashLong128_default hashLong128_default;
XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed;
XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret;
XXH3_dispatchx86_update update;
} dispatch128Functions_s;
static dispatch128Functions_s g_dispatch128 = { NULL, NULL, NULL };
static dispatch128Functions_s g_dispatch128 = { NULL, NULL, NULL, NULL };
static const dispatch128Functions_s k_dispatch128[NB_DISPATCHES] = {
/* scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar },
/* sse2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2 },
/* avx2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2 },
/* avx512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512 }
/* scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_128bits_update_scalar },
/* sse2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_128bits_update_sse2 },
/* avx2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_128bits_update_avx2 },
/* avx512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_128bits_update_avx512 }
};
static void setDispatch(void)
@ -552,7 +598,6 @@ static void setDispatch(void)
#endif
g_dispatch = k_dispatch[vecID];
g_dispatch128 = k_dispatch128[vecID];
g_coreFunc = k_coreFunc[vecID];
}
@ -603,9 +648,8 @@ XXH64_hash_t XXH3_64bits_withSecret_dispatch(const void* input, size_t len, cons
XXH_errorcode
XXH3_64bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len)
{
if (g_coreFunc.accumulate_512 == NULL) setDispatch();
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_64bits, g_coreFunc.accumulate_512, g_coreFunc.scrambleAcc);
if (g_dispatch.update == NULL) setDispatch();
return g_dispatch.update(state, (const xxh_u8*)input, len);
}
@ -656,7 +700,6 @@ XXH128_hash_t XXH3_128bits_withSecret_dispatch(const void* input, size_t len, co
XXH_errorcode
XXH3_128bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len)
{
if (g_coreFunc.accumulate_512 == NULL) setDispatch();
return XXH3_update(state, (const xxh_u8*)input, len,
XXH3_acc_128bits, g_coreFunc.accumulate_512, g_coreFunc.scrambleAcc);
if (g_dispatch128.update == NULL) setDispatch();
return g_dispatch128.update(state, (const xxh_u8*)input, len);
}

View File

@ -4,11 +4,11 @@ xxhsum(1) -- print or check xxHash non-cryptographic checksums
SYNOPSIS
--------
`xxhsum [<OPTION>] ... [<FILE>] ...`
`xxhsum [<OPTION>] ... [<FILE>] ...`
`xxhsum -b [<OPTION>] ...`
`xxh32sum` is equivalent to `xxhsum -H0`
`xxh64sum` is equivalent to `xxhsum -H1`
`xxh32sum` is equivalent to `xxhsum -H0`
`xxh64sum` is equivalent to `xxhsum -H1`
`xxh128sum` is equivalent to `xxhsum -H2`
@ -53,7 +53,7 @@ OPTIONS
* `-q`, `--quiet`:
Don't print OK for each successfully verified file
* `--strict`:
Return an error code if any line in the file is invalid,
not just if some checksums are wrong.
@ -72,6 +72,10 @@ OPTIONS
* `-b`:
Benchmark mode. See [EXAMPLES](#EXAMPLES) for details.
* `-b#`:
Specify ID of variant to be tested.
Multiple variants can be selected, separated by a ',' comma.
* `-B`<BLOCKSIZE>:
Only useful for benchmark mode (`-b`). See [EXAMPLES](#EXAMPLES) for details.
<BLOCKSIZE> specifies benchmark mode's test data block size in bytes.
@ -105,14 +109,23 @@ Read xxHash sums from specific files and check them
$ xxhsum -c xyz.xxh32 qux.xxh64
Benchmark xxHash algorithm for 16384 bytes data in 10 times. `xxhsum`
benchmarks all xxHash variants and output results to standard output.
The first column is the algorithm, thw second column is the source data
size in bytes, the third column is the number of hashes generated per
second (throughput), and finally the last column translates speed in
megabytes per second.
Benchmark xxHash algorithm.
By default, `xxhsum` benchmarks xxHash main variants
on a synthetic sample of 100 KB,
and print results into standard output.
The first column is the algorithm,
the second column is the source data size in bytes,
the third column is the number of hashes generated per second (throughput),
and finally the last column translates speed in megabytes per second.
$ xxhsum -b -i10 -B16384
$ xxhsum -b
In the following example,
the sample to hash is set to 16384 bytes,
the variants to be benched are selected by their IDs,
and each benchmark test is repeated 10 times, for increased accuracy.
$ xxhsum -b1,2,3 -i10 -B16384
BUGS
----

180
xxhsum.c
View File

@ -46,9 +46,10 @@
/* ************************************
* Includes
**************************************/
#include <limits.h>
#include <stdlib.h> /* malloc, calloc, free, exit */
#include <string.h> /* strcmp, memcpy */
#include <stdio.h> /* fprintf, fopen, ftello64, fread, stdin, stdout, _fileno (when present) */
#include <string.h> /* strcmp */
#include <sys/types.h> /* stat, stat64, _stat64 */
#include <sys/stat.h> /* stat, stat64, _stat64 */
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
@ -641,6 +642,22 @@ static U32 localXXH3_128b_secret(const void* buffer, size_t bufferSize, U32 seed
(void)seed;
return (U32)(XXH3_128bits_withSecret(buffer, bufferSize, g_benchSecretBuf, sizeof(g_benchSecretBuf)).low64);
}
static U32 localXXH3_stream(const void* buffer, size_t bufferSize, U32 seed)
{
XXH3_state_t state;
(void)seed;
XXH3_64bits_reset(&state);
XXH3_64bits_update(&state, buffer, bufferSize);
return (U32)XXH3_64bits_digest(&state);
}
static U32 localXXH128_stream(const void* buffer, size_t bufferSize, U32 seed)
{
XXH3_state_t state;
(void)seed;
XXH3_128bits_reset(&state);
XXH3_128bits_update(&state, buffer, bufferSize);
return (U32)(XXH3_128bits_digest(&state).low64);
}
typedef struct {
@ -648,7 +665,8 @@ typedef struct {
hashFunction func;
} hashInfo;
static const hashInfo g_hashesToBench[] = {
#define NB_HASHFUNC 10
static const hashInfo g_hashesToBench[NB_HASHFUNC] = {
{ "XXH32", &localXXH32 },
{ "XXH64", &localXXH64 },
{ "XXH3_64b", &localXXH3_64b },
@ -656,26 +674,36 @@ static const hashInfo g_hashesToBench[] = {
{ "XXH3_64b w/secret", &localXXH3_64b_secret },
{ "XXH128", &localXXH3_128b },
{ "XXH128 w/seed", &localXXH3_128b_seeded },
{ "XXH128 w/secret", &localXXH3_128b_secret }
{ "XXH128 w/secret", &localXXH3_128b_secret },
{ "XXH3_stream", &localXXH3_stream },
{ "XXH128_stream", &localXXH128_stream },
};
#define HASHNAME_MAX 29
#define NB_TESTFUNC (1 + 2 * NB_HASHFUNC)
static char g_testIDs[NB_TESTFUNC] = { 0 };
static const char k_testIDs_default[NB_TESTFUNC] = { 0,
1 /*XXH32*/, 0,
1 /*XXH64*/, 0,
1 /*XXH3*/, 0, 0, 0, 0, 0,
1 /*XXH128*/ };
static void BMK_benchHash(hashFunction h, const char* hName, const void* buffer, size_t bufferSize)
#define HASHNAME_MAX 29
static void BMK_benchHash(hashFunction h, const char* hName, int testID,
const void* buffer, size_t bufferSize)
{
U32 nbh_perIteration = (U32)((300 MB) / (bufferSize+1)) + 1; /* first loop conservatively aims for 300 MB/s */
U32 iterationNb;
U32 nbh_perIteration = (U32)((300 MB) / (bufferSize+1)) + 1; /* first iteration conservatively aims for 300 MB/s */
unsigned iterationNb, nbIterations = g_nbIterations + !g_nbIterations /* min 1 */;
double fastestH = 100000000.;
assert(HASHNAME_MAX > 2);
DISPLAYLEVEL(2, "\r%80s\r", ""); /* Clean display line */
if (g_nbIterations<1) g_nbIterations=1;
for (iterationNb = 1; iterationNb <= g_nbIterations; iterationNb++) {
for (iterationNb = 1; iterationNb <= nbIterations; iterationNb++) {
U32 r=0;
clock_t cStart;
DISPLAYLEVEL(2, "%1u-%-*.*s : %10u ->\r",
(unsigned)iterationNb,
HASHNAME_MAX-2, HASHNAME_MAX-2, hName,
DISPLAYLEVEL(2, "%2u-%-*.*s : %10u ->\r",
iterationNb,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize);
cStart = clock();
while (clock() == cStart); /* starts clock() at its exact beginning */
@ -685,7 +713,7 @@ static void BMK_benchHash(hashFunction h, const char* hName, const void* buffer,
for (u=0; u<nbh_perIteration; u++)
r += h(buffer, bufferSize, u);
}
if (r==0) DISPLAYLEVEL(3,".\r"); /* do something with r to defeat compiler "optimizing" away hash */
if (r==0) DISPLAYLEVEL(3,".\r"); /* do something with r to defeat compiler "optimizing" hash away */
{ clock_t const nbTicks = BMK_clockSpan(cStart);
double const ticksPerHash = ((double)nbTicks / TIMELOOP) / nbh_perIteration;
@ -720,23 +748,28 @@ static void BMK_benchHash(hashFunction h, const char* hName, const void* buffer,
if (nbh_perSecond > (double)(4000U<<20)) nbh_perSecond = (double)(4000U<<20); /* avoid overflow */
nbh_perIteration = (U32)nbh_perSecond;
}
iterationNb--; /* try again */
continue;
/* g_nbIterations==0 => quick evaluation, no claim of accuracy */
if (g_nbIterations>0) {
iterationNb--; /* new round for a more accurate speed evaluation */
continue;
}
}
if (ticksPerHash < fastestH) fastestH = ticksPerHash;
DISPLAYLEVEL(2, "%1u-%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \r",
(unsigned)iterationNb,
HASHNAME_MAX-2, HASHNAME_MAX-2, hName,
if (fastestH>0.) { /* avoid div by zero */
DISPLAYLEVEL(2, "%2u-%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \r",
iterationNb,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize,
(double)1 / fastestH,
((double)bufferSize / (1 MB)) / fastestH);
}
} }
{ double nbh_perSecond = (1 / fastestH) + 1;
if (nbh_perSecond > (double)(4000U<<20)) nbh_perSecond = (double)(4000U<<20); /* avoid overflow */
nbh_perIteration = (U32)nbh_perSecond;
}
}
DISPLAYLEVEL(1, "%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \n",
DISPLAYLEVEL(1, "%2i#%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \n",
testID,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize,
(double)1 / fastestH,
@ -748,49 +781,32 @@ static void BMK_benchHash(hashFunction h, const char* hName, const void* buffer,
/*!
* BMK_benchMem():
* specificTest: 0 == run all tests, 1+ runs specific test
* buffer: Must be 16-byte aligned.
* The real allocated size of buffer is supposed to be >= (bufferSize+3).
* returns: 0 on success, 1 if error (invalid mode selected)
*/
static int BMK_benchMem(const void* buffer, size_t bufferSize, U32 specificTest)
static void BMK_benchMem(const void* buffer, size_t bufferSize)
{
BMK_fillTestBuffer(g_benchSecretBuf, sizeof(g_benchSecretBuf));
assert((((size_t)buffer) & 15) == 0); /* ensure alignment */
{ const size_t NUM_HASHES = sizeof(g_hashesToBench) / sizeof(g_hashesToBench[0]);
size_t i;
assert(NUM_HASHES > 0);
/*
* specificTest == 0: all hashes
* Otherwise, it is the hashes in order, starting at 1.
* There are two entries per hash, with the first one (2 * i + 1) testing
* an aligned buffer and the second one (2 * i + 2) testing an unaligned
* buffer.
* For example, specificTest == 2 tests XXH32 with an unaligned buffer
* in the default setup.
*/
if (specificTest > 2 * NUM_HASHES) {
DISPLAY("Benchmark mode invalid.\n");
return 1;
}
for (i = 0; i < NUM_HASHES; i++) {
assert(g_hashesToBench[i].name != NULL);
BMK_fillTestBuffer(g_benchSecretBuf, sizeof(g_benchSecretBuf));
{ int i;
for (i = 1; i < NB_TESTFUNC; i++) {
int const hashFuncID = (i-1) / 2;
assert(g_hashesToBench[hashFuncID].name != NULL);
if (g_testIDs[i] == 0) continue;
/* aligned */
if (specificTest == 0 || specificTest == 2 * i + 1) {
BMK_benchHash(g_hashesToBench[i].func, g_hashesToBench[i].name, buffer, bufferSize);
if ((i % 2) == 1) {
BMK_benchHash(g_hashesToBench[hashFuncID].func, g_hashesToBench[hashFuncID].name, i, buffer, bufferSize);
}
/* unaligned */
if (specificTest == 0 || specificTest == 2 * i + 2) {
if ((i % 2) == 0) {
/* Append "unaligned". */
char* hashNameBuf = XXH_strcatDup(g_hashesToBench[i].name, " unaligned");
char* const hashNameBuf = XXH_strcatDup(g_hashesToBench[hashFuncID].name, " unaligned");
assert(hashNameBuf != NULL);
BMK_benchHash(g_hashesToBench[i].func, hashNameBuf, ((const char*)buffer)+3, bufferSize);
BMK_benchHash(g_hashesToBench[hashFuncID].func, hashNameBuf, i, ((const char*)buffer)+3, bufferSize);
free(hashNameBuf);
}
} }
return 0;
}
static size_t BMK_selectBenchedSize(const char* fileName)
@ -805,11 +821,9 @@ static size_t BMK_selectBenchedSize(const char* fileName)
}
static int BMK_benchFiles(char** fileNamesTable, int nbFiles, U32 specificTest)
static int BMK_benchFiles(char** fileNamesTable, int nbFiles)
{
int result = 0;
int fileIdx;
for (fileIdx=0; fileIdx<nbFiles; fileIdx++) {
const char* const inFileName = fileNamesTable[fileIdx];
assert(inFileName != NULL);
@ -823,12 +837,12 @@ static int BMK_benchFiles(char** fileNamesTable, int nbFiles, U32 specificTest)
if (inFile==NULL){
DISPLAY("Error: Could not open '%s': %s.\n", inFileName, strerror(errno));
free(buffer);
return 11;
exit(11);
}
if(!buffer) {
DISPLAY("\nError: Out of memory.\n");
fclose(inFile);
return 12;
exit(12);
}
/* Fill input buffer */
@ -837,25 +851,24 @@ static int BMK_benchFiles(char** fileNamesTable, int nbFiles, U32 specificTest)
if(readSize != benchedSize) {
DISPLAY("\nError: Could not read '%s': %s.\n", inFileName, strerror(errno));
free(buffer);
return 13;
exit(13);
} }
/* bench */
result |= BMK_benchMem(alignedBuffer, benchedSize, specificTest);
BMK_benchMem(alignedBuffer, benchedSize);
free(buffer);
} }
return result;
return 0;
}
static int BMK_benchInternal(size_t keySize, U32 specificTest)
static int BMK_benchInternal(size_t keySize)
{
void* const buffer = calloc(keySize+16+3, 1);
if (!buffer) {
if (buffer == NULL) {
DISPLAY("\nError: Out of memory.\n");
return 12;
exit(12);
}
{ const void* const alignedBuffer = ((char*)buffer+15) - (((size_t)((char*)buffer+15)) & 0xF); /* align on next 16 bytes */
@ -869,10 +882,10 @@ static int BMK_benchInternal(size_t keySize, U32 specificTest)
}
DISPLAYLEVEL(1, "... \n");
{ int const result = BMK_benchMem(alignedBuffer, keySize, specificTest);
free(buffer);
return result;
} }
BMK_benchMem(alignedBuffer, keySize);
free(buffer);
}
return 0;
}
@ -1631,8 +1644,8 @@ static int charToHex(char c)
/*
* Converts XXH32 canonical hexadecimal string `hashStr` to the big endian unsigned
* char array `dst`.
* Converts canonical ASCII hexadecimal string `hashStr`
* to the big endian binary representation in unsigned char array `dst`.
*
* Returns CANONICAL_FROM_STRING_INVALID_FORMAT if hashStr is not well formatted.
* Returns CANONICAL_FROM_STRING_OK if hashStr is parsed successfully.
@ -1930,7 +1943,7 @@ static int checkFile(const char* inFileName,
parseFileArg->inFileName = inFileName;
parseFileArg->inFile = inFile;
parseFileArg->lineMax = DEFAULT_LINE_LENGTH;
parseFileArg->lineBuf = (char*) malloc((size_t) parseFileArg->lineMax);
parseFileArg->lineBuf = (char*) malloc((size_t)parseFileArg->lineMax);
parseFileArg->blockSize = 64 * 1024;
parseFileArg->blockBuf = (char*) malloc(parseFileArg->blockSize);
parseFileArg->strictMode = strictMode;
@ -1938,6 +1951,11 @@ static int checkFile(const char* inFileName,
parseFileArg->warn = warn;
parseFileArg->quiet = quiet;
if ( (parseFileArg->lineBuf == NULL)
|| (parseFileArg->blockBuf == NULL) ) {
DISPLAY("Error: : memory allocation failed \n");
exit(1);
}
parseFile1(parseFileArg);
free(parseFileArg->blockBuf);
@ -2106,7 +2124,8 @@ static int XXH_main(int argc, char** argv)
U32 strictMode = 0;
U32 statusOnly = 0;
U32 warn = 0;
U32 specificTest = 0;
U32 selectBenchIDs= 0; /* 0 == use default k_testIDs_default, kBenchAll == bench all */
static const U32 kBenchAll = 99;
size_t keySize = XXH_DEFAULT_SAMPLE_SIZE;
algoType algo = g_defaultAlgo;
endianess displayEndianess = big_endian;
@ -2121,14 +2140,16 @@ static int XXH_main(int argc, char** argv)
if(!argument) continue; /* Protection if arguments are empty */
if (!strcmp(argument, "--little-endian")) { displayEndianess = little_endian; continue; }
if (!strcmp(argument, "--check")) { fileCheckMode = 1; continue; }
if (!strcmp(argument, "--benchmark-all")) { benchmarkMode = 1; selectBenchIDs = kBenchAll; continue; }
if (!strcmp(argument, "--bench-all")) { benchmarkMode = 1; selectBenchIDs = kBenchAll; continue; }
if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
if (!strcmp(argument, "--little-endian")) { displayEndianess = little_endian; continue; }
if (!strcmp(argument, "--strict")) { strictMode = 1; continue; }
if (!strcmp(argument, "--status")) { statusOnly = 1; continue; }
if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; }
if (!strcmp(argument, "--warn")) { warn = 1; continue; }
if (!strcmp(argument, "--help")) { return usage_advanced(exename); }
if (!strcmp(argument, "--version")) { DISPLAY(WELCOME_MESSAGE(exename)); return 0; }
if (!strcmp(argument, "--version")) { DISPLAY(WELCOME_MESSAGE(exename)); BMK_sanityCheck(); return 0; }
if (*argument!='-') {
if (filenamesStart==0) filenamesStart=i; /* only supports a continuous list of filenames */
@ -2173,7 +2194,14 @@ static int XXH_main(int argc, char** argv)
case 'b':
argument++;
benchmarkMode = 1;
specificTest = readU32FromChar(&argument); /* select one specific test */
do {
if (*argument == ',') argument++;
selectBenchIDs = readU32FromChar(&argument); /* select one specific test */
if (selectBenchIDs < NB_TESTFUNC) {
g_testIDs[selectBenchIDs] = 1;
} else
selectBenchIDs = kBenchAll;
} while (*argument == ',');
break;
/* Modify Nb Iterations (benchmark only) */
@ -2204,8 +2232,10 @@ static int XXH_main(int argc, char** argv)
if (benchmarkMode) {
DISPLAYLEVEL(2, WELCOME_MESSAGE(exename) );
BMK_sanityCheck();
if (filenamesStart==0) return BMK_benchInternal(keySize, specificTest);
return BMK_benchFiles(argv+filenamesStart, argc-filenamesStart, specificTest);
if (selectBenchIDs == 0) memcpy(g_testIDs, k_testIDs_default, sizeof(g_testIDs));
if (selectBenchIDs == kBenchAll) memset(g_testIDs, 1, sizeof(g_testIDs));
if (filenamesStart==0) return BMK_benchInternal(keySize);
return BMK_benchFiles(argv+filenamesStart, argc-filenamesStart);
}
/* Check if input is defined as console; trigger an error in this case */