mirror of
https://github.com/FEX-Emu/xxHash.git
synced 2024-11-23 22:49:39 +00:00
Merge pull request #390 from Cyan4973/newBench
Updated benchmark module
This commit is contained in:
commit
4cdfe2f442
10
Makefile
10
Makefile
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
35
xxhsum.1.md
35
xxhsum.1.md
@ -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
180
xxhsum.c
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user