127b27ec6Sopenharmony_ci/*
227b27ec6Sopenharmony_ci    bench.c - Demo program to benchmark open-source compression algorithms
327b27ec6Sopenharmony_ci    Copyright (C) Yann Collet 2012-2020
427b27ec6Sopenharmony_ci
527b27ec6Sopenharmony_ci    GPL v2 License
627b27ec6Sopenharmony_ci
727b27ec6Sopenharmony_ci    This program is free software; you can redistribute it and/or modify
827b27ec6Sopenharmony_ci    it under the terms of the GNU General Public License as published by
927b27ec6Sopenharmony_ci    the Free Software Foundation; either version 2 of the License, or
1027b27ec6Sopenharmony_ci    (at your option) any later version.
1127b27ec6Sopenharmony_ci
1227b27ec6Sopenharmony_ci    This program is distributed in the hope that it will be useful,
1327b27ec6Sopenharmony_ci    but WITHOUT ANY WARRANTY; without even the implied warranty of
1427b27ec6Sopenharmony_ci    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1527b27ec6Sopenharmony_ci    GNU General Public License for more details.
1627b27ec6Sopenharmony_ci
1727b27ec6Sopenharmony_ci    You should have received a copy of the GNU General Public License along
1827b27ec6Sopenharmony_ci    with this program; if not, write to the Free Software Foundation, Inc.,
1927b27ec6Sopenharmony_ci    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2027b27ec6Sopenharmony_ci
2127b27ec6Sopenharmony_ci    You can contact the author at :
2227b27ec6Sopenharmony_ci    - LZ4 homepage : http://www.lz4.org
2327b27ec6Sopenharmony_ci    - LZ4 source repository : https://github.com/lz4/lz4
2427b27ec6Sopenharmony_ci*/
2527b27ec6Sopenharmony_ci
2627b27ec6Sopenharmony_ci
2727b27ec6Sopenharmony_ci/*-************************************
2827b27ec6Sopenharmony_ci*  Compiler options
2927b27ec6Sopenharmony_ci**************************************/
3027b27ec6Sopenharmony_ci#ifdef _MSC_VER    /* Visual Studio */
3127b27ec6Sopenharmony_ci#  pragma warning(disable : 4127)    /* disable: C4127: conditional expression is constant */
3227b27ec6Sopenharmony_ci#endif
3327b27ec6Sopenharmony_ci
3427b27ec6Sopenharmony_ci
3527b27ec6Sopenharmony_ci/* *************************************
3627b27ec6Sopenharmony_ci*  Includes
3727b27ec6Sopenharmony_ci***************************************/
3827b27ec6Sopenharmony_ci#include "platform.h"    /* Compiler options */
3927b27ec6Sopenharmony_ci#include "util.h"        /* UTIL_GetFileSize, UTIL_sleep */
4027b27ec6Sopenharmony_ci#include <stdlib.h>      /* malloc, free */
4127b27ec6Sopenharmony_ci#include <string.h>      /* memset */
4227b27ec6Sopenharmony_ci#include <stdio.h>       /* fprintf, fopen, ftello */
4327b27ec6Sopenharmony_ci#include <time.h>        /* clock_t, clock, CLOCKS_PER_SEC */
4427b27ec6Sopenharmony_ci#include <assert.h>      /* assert */
4527b27ec6Sopenharmony_ci
4627b27ec6Sopenharmony_ci#include "datagen.h"     /* RDG_genBuffer */
4727b27ec6Sopenharmony_ci#include "xxhash.h"
4827b27ec6Sopenharmony_ci#include "bench.h"
4927b27ec6Sopenharmony_ci
5027b27ec6Sopenharmony_ci#define LZ4_STATIC_LINKING_ONLY
5127b27ec6Sopenharmony_ci#include "lz4.h"
5227b27ec6Sopenharmony_ci#define LZ4_HC_STATIC_LINKING_ONLY
5327b27ec6Sopenharmony_ci#include "lz4hc.h"
5427b27ec6Sopenharmony_ci#include "lz4frame.h"   /* LZ4F_decompress */
5527b27ec6Sopenharmony_ci
5627b27ec6Sopenharmony_ci
5727b27ec6Sopenharmony_ci/* *************************************
5827b27ec6Sopenharmony_ci*  Constants
5927b27ec6Sopenharmony_ci***************************************/
6027b27ec6Sopenharmony_ci#ifndef LZ4_GIT_COMMIT_STRING
6127b27ec6Sopenharmony_ci#  define LZ4_GIT_COMMIT_STRING ""
6227b27ec6Sopenharmony_ci#else
6327b27ec6Sopenharmony_ci#  define LZ4_GIT_COMMIT_STRING LZ4_EXPAND_AND_QUOTE(LZ4_GIT_COMMIT)
6427b27ec6Sopenharmony_ci#endif
6527b27ec6Sopenharmony_ci
6627b27ec6Sopenharmony_ci#define NBSECONDS             3
6727b27ec6Sopenharmony_ci#define TIMELOOP_MICROSEC     1*1000000ULL /* 1 second */
6827b27ec6Sopenharmony_ci#define TIMELOOP_NANOSEC      1*1000000000ULL /* 1 second */
6927b27ec6Sopenharmony_ci#define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */
7027b27ec6Sopenharmony_ci#define COOLPERIOD_SEC        10
7127b27ec6Sopenharmony_ci#define DECOMP_MULT           1 /* test decompression DECOMP_MULT times longer than compression */
7227b27ec6Sopenharmony_ci
7327b27ec6Sopenharmony_ci#define KB *(1 <<10)
7427b27ec6Sopenharmony_ci#define MB *(1 <<20)
7527b27ec6Sopenharmony_ci#define GB *(1U<<30)
7627b27ec6Sopenharmony_ci
7727b27ec6Sopenharmony_ci#define LZ4_MAX_DICT_SIZE (64 KB)
7827b27ec6Sopenharmony_ci
7927b27ec6Sopenharmony_cistatic const size_t maxMemory = (sizeof(size_t)==4)  ?  (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31));
8027b27ec6Sopenharmony_ci
8127b27ec6Sopenharmony_cistatic U32 g_compressibilityDefault = 50;
8227b27ec6Sopenharmony_ci
8327b27ec6Sopenharmony_ci
8427b27ec6Sopenharmony_ci/* *************************************
8527b27ec6Sopenharmony_ci*  console display
8627b27ec6Sopenharmony_ci***************************************/
8727b27ec6Sopenharmony_ci#define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
8827b27ec6Sopenharmony_ci#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
8927b27ec6Sopenharmony_cistatic U32 g_displayLevel = 2;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
9027b27ec6Sopenharmony_ci
9127b27ec6Sopenharmony_ci#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
9227b27ec6Sopenharmony_ci            if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \
9327b27ec6Sopenharmony_ci            { g_time = clock(); DISPLAY(__VA_ARGS__); \
9427b27ec6Sopenharmony_ci            if (g_displayLevel>=4) fflush(stdout); } }
9527b27ec6Sopenharmony_cistatic const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
9627b27ec6Sopenharmony_cistatic clock_t g_time = 0;
9727b27ec6Sopenharmony_ci
9827b27ec6Sopenharmony_ci
9927b27ec6Sopenharmony_ci/* *************************************
10027b27ec6Sopenharmony_ci*  DEBUG and error conditions
10127b27ec6Sopenharmony_ci***************************************/
10227b27ec6Sopenharmony_ci#ifndef DEBUG
10327b27ec6Sopenharmony_ci#  define DEBUG 0
10427b27ec6Sopenharmony_ci#endif
10527b27ec6Sopenharmony_ci#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
10627b27ec6Sopenharmony_ci#define END_PROCESS(error, ...)                                             \
10727b27ec6Sopenharmony_ci{                                                                         \
10827b27ec6Sopenharmony_ci    DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
10927b27ec6Sopenharmony_ci    DISPLAYLEVEL(1, "Error %i : ", error);                                \
11027b27ec6Sopenharmony_ci    DISPLAYLEVEL(1, __VA_ARGS__);                                         \
11127b27ec6Sopenharmony_ci    DISPLAYLEVEL(1, "\n");                                                \
11227b27ec6Sopenharmony_ci    exit(error);                                                          \
11327b27ec6Sopenharmony_ci}
11427b27ec6Sopenharmony_ci
11527b27ec6Sopenharmony_ci#define LZ4_isError(errcode) (errcode==0)
11627b27ec6Sopenharmony_ci
11727b27ec6Sopenharmony_ci
11827b27ec6Sopenharmony_ci/* *************************************
11927b27ec6Sopenharmony_ci*  Benchmark Parameters
12027b27ec6Sopenharmony_ci***************************************/
12127b27ec6Sopenharmony_cistatic U32 g_nbSeconds = NBSECONDS;
12227b27ec6Sopenharmony_cistatic size_t g_blockSize = 0;
12327b27ec6Sopenharmony_ciint g_additionalParam = 0;
12427b27ec6Sopenharmony_ciint g_benchSeparately = 0;
12527b27ec6Sopenharmony_ciint g_decodeOnly = 0;
12627b27ec6Sopenharmony_ciunsigned g_skipChecksums = 0;
12727b27ec6Sopenharmony_ci
12827b27ec6Sopenharmony_civoid BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; }
12927b27ec6Sopenharmony_ci
13027b27ec6Sopenharmony_civoid BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }
13127b27ec6Sopenharmony_ci
13227b27ec6Sopenharmony_civoid BMK_setNbSeconds(unsigned nbSeconds)
13327b27ec6Sopenharmony_ci{
13427b27ec6Sopenharmony_ci    g_nbSeconds = nbSeconds;
13527b27ec6Sopenharmony_ci    DISPLAYLEVEL(3, "- test >= %u seconds per compression / decompression -\n", g_nbSeconds);
13627b27ec6Sopenharmony_ci}
13727b27ec6Sopenharmony_ci
13827b27ec6Sopenharmony_civoid BMK_setBlockSize(size_t blockSize) { g_blockSize = blockSize; }
13927b27ec6Sopenharmony_ci
14027b27ec6Sopenharmony_civoid BMK_setBenchSeparately(int separate) { g_benchSeparately = (separate!=0); }
14127b27ec6Sopenharmony_ci
14227b27ec6Sopenharmony_civoid BMK_setDecodeOnlyMode(int set) { g_decodeOnly = (set!=0); }
14327b27ec6Sopenharmony_ci
14427b27ec6Sopenharmony_civoid BMK_skipChecksums(int skip) { g_skipChecksums = (skip!=0); }
14527b27ec6Sopenharmony_ci
14627b27ec6Sopenharmony_ci
14727b27ec6Sopenharmony_ci/* *************************************
14827b27ec6Sopenharmony_ci *  Compression state management
14927b27ec6Sopenharmony_ci***************************************/
15027b27ec6Sopenharmony_ci
15127b27ec6Sopenharmony_cistruct compressionParameters
15227b27ec6Sopenharmony_ci{
15327b27ec6Sopenharmony_ci    int cLevel;
15427b27ec6Sopenharmony_ci    const char* dictBuf;
15527b27ec6Sopenharmony_ci    int dictSize;
15627b27ec6Sopenharmony_ci
15727b27ec6Sopenharmony_ci    LZ4_stream_t* LZ4_stream;
15827b27ec6Sopenharmony_ci    LZ4_stream_t* LZ4_dictStream;
15927b27ec6Sopenharmony_ci    LZ4_streamHC_t* LZ4_streamHC;
16027b27ec6Sopenharmony_ci    LZ4_streamHC_t* LZ4_dictStreamHC;
16127b27ec6Sopenharmony_ci
16227b27ec6Sopenharmony_ci    void (*initFunction)(
16327b27ec6Sopenharmony_ci        struct compressionParameters* pThis);
16427b27ec6Sopenharmony_ci    void (*resetFunction)(
16527b27ec6Sopenharmony_ci        const struct compressionParameters* pThis);
16627b27ec6Sopenharmony_ci    int (*blockFunction)(
16727b27ec6Sopenharmony_ci        const struct compressionParameters* pThis,
16827b27ec6Sopenharmony_ci        const char* src, char* dst, int srcSize, int dstSize);
16927b27ec6Sopenharmony_ci    void (*cleanupFunction)(
17027b27ec6Sopenharmony_ci        const struct compressionParameters* pThis);
17127b27ec6Sopenharmony_ci};
17227b27ec6Sopenharmony_ci
17327b27ec6Sopenharmony_cistatic void
17427b27ec6Sopenharmony_ciLZ4_compressInitNoStream(struct compressionParameters* pThis)
17527b27ec6Sopenharmony_ci{
17627b27ec6Sopenharmony_ci    pThis->LZ4_stream = NULL;
17727b27ec6Sopenharmony_ci    pThis->LZ4_dictStream = NULL;
17827b27ec6Sopenharmony_ci    pThis->LZ4_streamHC = NULL;
17927b27ec6Sopenharmony_ci    pThis->LZ4_dictStreamHC = NULL;
18027b27ec6Sopenharmony_ci}
18127b27ec6Sopenharmony_ci
18227b27ec6Sopenharmony_cistatic void
18327b27ec6Sopenharmony_ciLZ4_compressInitStream(struct compressionParameters* pThis)
18427b27ec6Sopenharmony_ci{
18527b27ec6Sopenharmony_ci    pThis->LZ4_stream = LZ4_createStream();
18627b27ec6Sopenharmony_ci    pThis->LZ4_dictStream = LZ4_createStream();
18727b27ec6Sopenharmony_ci    pThis->LZ4_streamHC = NULL;
18827b27ec6Sopenharmony_ci    pThis->LZ4_dictStreamHC = NULL;
18927b27ec6Sopenharmony_ci    LZ4_loadDict(pThis->LZ4_dictStream, pThis->dictBuf, pThis->dictSize);
19027b27ec6Sopenharmony_ci}
19127b27ec6Sopenharmony_ci
19227b27ec6Sopenharmony_cistatic void
19327b27ec6Sopenharmony_ciLZ4_compressInitStreamHC(struct compressionParameters* pThis)
19427b27ec6Sopenharmony_ci{
19527b27ec6Sopenharmony_ci    pThis->LZ4_stream = NULL;
19627b27ec6Sopenharmony_ci    pThis->LZ4_dictStream = NULL;
19727b27ec6Sopenharmony_ci    pThis->LZ4_streamHC = LZ4_createStreamHC();
19827b27ec6Sopenharmony_ci    pThis->LZ4_dictStreamHC = LZ4_createStreamHC();
19927b27ec6Sopenharmony_ci    LZ4_loadDictHC(pThis->LZ4_dictStreamHC, pThis->dictBuf, pThis->dictSize);
20027b27ec6Sopenharmony_ci}
20127b27ec6Sopenharmony_ci
20227b27ec6Sopenharmony_cistatic void
20327b27ec6Sopenharmony_ciLZ4_compressResetNoStream(const struct compressionParameters* pThis)
20427b27ec6Sopenharmony_ci{
20527b27ec6Sopenharmony_ci    (void)pThis;
20627b27ec6Sopenharmony_ci}
20727b27ec6Sopenharmony_ci
20827b27ec6Sopenharmony_cistatic void
20927b27ec6Sopenharmony_ciLZ4_compressResetStream(const struct compressionParameters* pThis)
21027b27ec6Sopenharmony_ci{
21127b27ec6Sopenharmony_ci    LZ4_resetStream_fast(pThis->LZ4_stream);
21227b27ec6Sopenharmony_ci    LZ4_attach_dictionary(pThis->LZ4_stream, pThis->LZ4_dictStream);
21327b27ec6Sopenharmony_ci}
21427b27ec6Sopenharmony_ci
21527b27ec6Sopenharmony_cistatic void
21627b27ec6Sopenharmony_ciLZ4_compressResetStreamHC(const struct compressionParameters* pThis)
21727b27ec6Sopenharmony_ci{
21827b27ec6Sopenharmony_ci    LZ4_resetStreamHC_fast(pThis->LZ4_streamHC, pThis->cLevel);
21927b27ec6Sopenharmony_ci    LZ4_attach_HC_dictionary(pThis->LZ4_streamHC, pThis->LZ4_dictStreamHC);
22027b27ec6Sopenharmony_ci}
22127b27ec6Sopenharmony_ci
22227b27ec6Sopenharmony_cistatic int
22327b27ec6Sopenharmony_ciLZ4_compressBlockNoStream(const struct compressionParameters* pThis,
22427b27ec6Sopenharmony_ci                          const char* src, char* dst,
22527b27ec6Sopenharmony_ci                          int srcSize, int dstSize)
22627b27ec6Sopenharmony_ci{
22727b27ec6Sopenharmony_ci    int const acceleration = (pThis->cLevel < 0) ? -pThis->cLevel + 1 : 1;
22827b27ec6Sopenharmony_ci    return LZ4_compress_fast(src, dst, srcSize, dstSize, acceleration);
22927b27ec6Sopenharmony_ci}
23027b27ec6Sopenharmony_ci
23127b27ec6Sopenharmony_cistatic int
23227b27ec6Sopenharmony_ciLZ4_compressBlockNoStreamHC(const struct compressionParameters* pThis,
23327b27ec6Sopenharmony_ci                            const char* src, char* dst,
23427b27ec6Sopenharmony_ci                            int srcSize, int dstSize)
23527b27ec6Sopenharmony_ci{
23627b27ec6Sopenharmony_ci    return LZ4_compress_HC(src, dst, srcSize, dstSize, pThis->cLevel);
23727b27ec6Sopenharmony_ci}
23827b27ec6Sopenharmony_ci
23927b27ec6Sopenharmony_cistatic int
24027b27ec6Sopenharmony_ciLZ4_compressBlockStream(const struct compressionParameters* pThis,
24127b27ec6Sopenharmony_ci                        const char* src, char* dst,
24227b27ec6Sopenharmony_ci                        int srcSize, int dstSize)
24327b27ec6Sopenharmony_ci{
24427b27ec6Sopenharmony_ci    int const acceleration = (pThis->cLevel < 0) ? -pThis->cLevel + 1 : 1;
24527b27ec6Sopenharmony_ci    return LZ4_compress_fast_continue(pThis->LZ4_stream, src, dst, srcSize, dstSize, acceleration);
24627b27ec6Sopenharmony_ci}
24727b27ec6Sopenharmony_ci
24827b27ec6Sopenharmony_cistatic int
24927b27ec6Sopenharmony_ciLZ4_compressBlockStreamHC(const struct compressionParameters* pThis,
25027b27ec6Sopenharmony_ci                          const char* src, char* dst,
25127b27ec6Sopenharmony_ci                          int srcSize, int dstSize)
25227b27ec6Sopenharmony_ci{
25327b27ec6Sopenharmony_ci    return LZ4_compress_HC_continue(pThis->LZ4_streamHC, src, dst, srcSize, dstSize);
25427b27ec6Sopenharmony_ci}
25527b27ec6Sopenharmony_ci
25627b27ec6Sopenharmony_cistatic void
25727b27ec6Sopenharmony_ciLZ4_compressCleanupNoStream(const struct compressionParameters* pThis)
25827b27ec6Sopenharmony_ci{
25927b27ec6Sopenharmony_ci    (void)pThis;
26027b27ec6Sopenharmony_ci}
26127b27ec6Sopenharmony_ci
26227b27ec6Sopenharmony_cistatic void
26327b27ec6Sopenharmony_ciLZ4_compressCleanupStream(const struct compressionParameters* pThis)
26427b27ec6Sopenharmony_ci{
26527b27ec6Sopenharmony_ci    LZ4_freeStream(pThis->LZ4_stream);
26627b27ec6Sopenharmony_ci    LZ4_freeStream(pThis->LZ4_dictStream);
26727b27ec6Sopenharmony_ci}
26827b27ec6Sopenharmony_ci
26927b27ec6Sopenharmony_cistatic void
27027b27ec6Sopenharmony_ciLZ4_compressCleanupStreamHC(const struct compressionParameters* pThis)
27127b27ec6Sopenharmony_ci{
27227b27ec6Sopenharmony_ci    LZ4_freeStreamHC(pThis->LZ4_streamHC);
27327b27ec6Sopenharmony_ci    LZ4_freeStreamHC(pThis->LZ4_dictStreamHC);
27427b27ec6Sopenharmony_ci}
27527b27ec6Sopenharmony_ci
27627b27ec6Sopenharmony_cistatic void
27727b27ec6Sopenharmony_ciLZ4_buildCompressionParameters(struct compressionParameters* pParams,
27827b27ec6Sopenharmony_ci                               int cLevel,
27927b27ec6Sopenharmony_ci                         const char* dictBuf, int dictSize)
28027b27ec6Sopenharmony_ci{
28127b27ec6Sopenharmony_ci    pParams->cLevel = cLevel;
28227b27ec6Sopenharmony_ci    pParams->dictBuf = dictBuf;
28327b27ec6Sopenharmony_ci    pParams->dictSize = dictSize;
28427b27ec6Sopenharmony_ci
28527b27ec6Sopenharmony_ci    if (dictSize) {
28627b27ec6Sopenharmony_ci        if (cLevel < LZ4HC_CLEVEL_MIN) {
28727b27ec6Sopenharmony_ci            pParams->initFunction = LZ4_compressInitStream;
28827b27ec6Sopenharmony_ci            pParams->resetFunction = LZ4_compressResetStream;
28927b27ec6Sopenharmony_ci            pParams->blockFunction = LZ4_compressBlockStream;
29027b27ec6Sopenharmony_ci            pParams->cleanupFunction = LZ4_compressCleanupStream;
29127b27ec6Sopenharmony_ci        } else {
29227b27ec6Sopenharmony_ci            pParams->initFunction = LZ4_compressInitStreamHC;
29327b27ec6Sopenharmony_ci            pParams->resetFunction = LZ4_compressResetStreamHC;
29427b27ec6Sopenharmony_ci            pParams->blockFunction = LZ4_compressBlockStreamHC;
29527b27ec6Sopenharmony_ci            pParams->cleanupFunction = LZ4_compressCleanupStreamHC;
29627b27ec6Sopenharmony_ci        }
29727b27ec6Sopenharmony_ci    } else {
29827b27ec6Sopenharmony_ci        pParams->initFunction = LZ4_compressInitNoStream;
29927b27ec6Sopenharmony_ci        pParams->resetFunction = LZ4_compressResetNoStream;
30027b27ec6Sopenharmony_ci        pParams->cleanupFunction = LZ4_compressCleanupNoStream;
30127b27ec6Sopenharmony_ci
30227b27ec6Sopenharmony_ci        if (cLevel < LZ4HC_CLEVEL_MIN) {
30327b27ec6Sopenharmony_ci            pParams->blockFunction = LZ4_compressBlockNoStream;
30427b27ec6Sopenharmony_ci        } else {
30527b27ec6Sopenharmony_ci            pParams->blockFunction = LZ4_compressBlockNoStreamHC;
30627b27ec6Sopenharmony_ci        }
30727b27ec6Sopenharmony_ci    }
30827b27ec6Sopenharmony_ci}
30927b27ec6Sopenharmony_ci
31027b27ec6Sopenharmony_ci
31127b27ec6Sopenharmony_citypedef int (*DecFunction_f)(const char* src, char* dst,
31227b27ec6Sopenharmony_ci                             int srcSize, int dstCapacity,
31327b27ec6Sopenharmony_ci                             const char* dictStart, int dictSize);
31427b27ec6Sopenharmony_ci
31527b27ec6Sopenharmony_cistatic LZ4F_dctx* g_dctx = NULL;
31627b27ec6Sopenharmony_ci
31727b27ec6Sopenharmony_cistatic int
31827b27ec6Sopenharmony_ciLZ4F_decompress_binding(const char* src, char* dst,
31927b27ec6Sopenharmony_ci                        int srcSize, int dstCapacity,
32027b27ec6Sopenharmony_ci                  const char* dictStart, int dictSize)
32127b27ec6Sopenharmony_ci{
32227b27ec6Sopenharmony_ci    size_t dstSize = (size_t)dstCapacity;
32327b27ec6Sopenharmony_ci    size_t readSize = (size_t)srcSize;
32427b27ec6Sopenharmony_ci    LZ4F_decompressOptions_t dOpt = { 1, 0, 0, 0 };
32527b27ec6Sopenharmony_ci    size_t decStatus;
32627b27ec6Sopenharmony_ci    dOpt.skipChecksums = g_skipChecksums;
32727b27ec6Sopenharmony_ci    decStatus = LZ4F_decompress(g_dctx,
32827b27ec6Sopenharmony_ci                    dst, &dstSize,
32927b27ec6Sopenharmony_ci                    src, &readSize,
33027b27ec6Sopenharmony_ci                    &dOpt);
33127b27ec6Sopenharmony_ci    if ( (decStatus == 0)   /* decompression successful */
33227b27ec6Sopenharmony_ci      && ((int)readSize==srcSize) /* consume all input */ )
33327b27ec6Sopenharmony_ci        return (int)dstSize;
33427b27ec6Sopenharmony_ci    /* else, error */
33527b27ec6Sopenharmony_ci    return -1;
33627b27ec6Sopenharmony_ci    (void)dictStart; (void)dictSize;  /* not compatible with dictionary yet */
33727b27ec6Sopenharmony_ci}
33827b27ec6Sopenharmony_ci
33927b27ec6Sopenharmony_ci
34027b27ec6Sopenharmony_ci/* ********************************************************
34127b27ec6Sopenharmony_ci*  Bench functions
34227b27ec6Sopenharmony_ci**********************************************************/
34327b27ec6Sopenharmony_citypedef struct {
34427b27ec6Sopenharmony_ci    const char* srcPtr;
34527b27ec6Sopenharmony_ci    size_t srcSize;
34627b27ec6Sopenharmony_ci    char*  cPtr;
34727b27ec6Sopenharmony_ci    size_t cRoom;
34827b27ec6Sopenharmony_ci    size_t cSize;
34927b27ec6Sopenharmony_ci    char*  resPtr;
35027b27ec6Sopenharmony_ci    size_t resSize;
35127b27ec6Sopenharmony_ci} blockParam_t;
35227b27ec6Sopenharmony_ci
35327b27ec6Sopenharmony_ci#define MIN(a,b) ((a)<(b) ? (a) : (b))
35427b27ec6Sopenharmony_ci#define MAX(a,b) ((a)>(b) ? (a) : (b))
35527b27ec6Sopenharmony_ci
35627b27ec6Sopenharmony_cistatic int BMK_benchMem(const void* srcBuffer, size_t srcSize,
35727b27ec6Sopenharmony_ci                        const char* displayName, int cLevel,
35827b27ec6Sopenharmony_ci                        const size_t* fileSizes, U32 nbFiles,
35927b27ec6Sopenharmony_ci                        const char* dictBuf, int dictSize)
36027b27ec6Sopenharmony_ci{
36127b27ec6Sopenharmony_ci    size_t const blockSize = (g_blockSize>=32 && !g_decodeOnly ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ;
36227b27ec6Sopenharmony_ci    U32 const maxNbBlocks = (U32)((srcSize + (blockSize-1)) / blockSize) + nbFiles;
36327b27ec6Sopenharmony_ci    blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t));
36427b27ec6Sopenharmony_ci    size_t const maxCompressedSize = (size_t)LZ4_compressBound((int)srcSize) + (maxNbBlocks * 1024);   /* add some room for safety */
36527b27ec6Sopenharmony_ci    void* const compressedBuffer = malloc(maxCompressedSize);
36627b27ec6Sopenharmony_ci    size_t const decMultiplier = g_decodeOnly ? 255 : 1;
36727b27ec6Sopenharmony_ci    size_t const maxInSize = (size_t)LZ4_MAX_INPUT_SIZE / decMultiplier;
36827b27ec6Sopenharmony_ci    size_t const maxDecSize = srcSize < maxInSize ? srcSize * decMultiplier : LZ4_MAX_INPUT_SIZE;
36927b27ec6Sopenharmony_ci    void* const resultBuffer = malloc(maxDecSize);
37027b27ec6Sopenharmony_ci    U32 nbBlocks;
37127b27ec6Sopenharmony_ci    struct compressionParameters compP;
37227b27ec6Sopenharmony_ci
37327b27ec6Sopenharmony_ci    /* checks */
37427b27ec6Sopenharmony_ci    if (!compressedBuffer || !resultBuffer || !blockTable)
37527b27ec6Sopenharmony_ci        END_PROCESS(31, "allocation error : not enough memory");
37627b27ec6Sopenharmony_ci
37727b27ec6Sopenharmony_ci    if (strlen(displayName)>17) displayName += strlen(displayName)-17;   /* can only display 17 characters */
37827b27ec6Sopenharmony_ci
37927b27ec6Sopenharmony_ci    /* init */
38027b27ec6Sopenharmony_ci    LZ4_buildCompressionParameters(&compP, cLevel, dictBuf, dictSize);
38127b27ec6Sopenharmony_ci    compP.initFunction(&compP);
38227b27ec6Sopenharmony_ci    if (g_dctx==NULL) {
38327b27ec6Sopenharmony_ci        LZ4F_createDecompressionContext(&g_dctx, LZ4F_VERSION);
38427b27ec6Sopenharmony_ci        if (g_dctx==NULL)
38527b27ec6Sopenharmony_ci            END_PROCESS(1, "allocation error - decompression state");
38627b27ec6Sopenharmony_ci    }
38727b27ec6Sopenharmony_ci
38827b27ec6Sopenharmony_ci    /* Init blockTable data */
38927b27ec6Sopenharmony_ci    {   const char* srcPtr = (const char*)srcBuffer;
39027b27ec6Sopenharmony_ci        char* cPtr = (char*)compressedBuffer;
39127b27ec6Sopenharmony_ci        char* resPtr = (char*)resultBuffer;
39227b27ec6Sopenharmony_ci        U32 fileNb;
39327b27ec6Sopenharmony_ci        for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) {
39427b27ec6Sopenharmony_ci            size_t remaining = fileSizes[fileNb];
39527b27ec6Sopenharmony_ci            U32 const nbBlocksforThisFile = (U32)((remaining + (blockSize-1)) / blockSize);
39627b27ec6Sopenharmony_ci            U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
39727b27ec6Sopenharmony_ci            for ( ; nbBlocks<blockEnd; nbBlocks++) {
39827b27ec6Sopenharmony_ci                size_t const thisBlockSize = MIN(remaining, blockSize);
39927b27ec6Sopenharmony_ci                size_t const resMaxSize = thisBlockSize * decMultiplier;
40027b27ec6Sopenharmony_ci                size_t const resCapa = (thisBlockSize < maxInSize) ? resMaxSize : LZ4_MAX_INPUT_SIZE;
40127b27ec6Sopenharmony_ci                blockTable[nbBlocks].srcPtr = srcPtr;
40227b27ec6Sopenharmony_ci                blockTable[nbBlocks].cPtr = cPtr;
40327b27ec6Sopenharmony_ci                blockTable[nbBlocks].resPtr = resPtr;
40427b27ec6Sopenharmony_ci                blockTable[nbBlocks].srcSize = thisBlockSize;
40527b27ec6Sopenharmony_ci                blockTable[nbBlocks].cRoom = (size_t)LZ4_compressBound((int)thisBlockSize);
40627b27ec6Sopenharmony_ci                srcPtr += thisBlockSize;
40727b27ec6Sopenharmony_ci                cPtr += blockTable[nbBlocks].cRoom;
40827b27ec6Sopenharmony_ci                resPtr += resCapa;
40927b27ec6Sopenharmony_ci                remaining -= thisBlockSize;
41027b27ec6Sopenharmony_ci    }   }   }
41127b27ec6Sopenharmony_ci
41227b27ec6Sopenharmony_ci    /* warming up memory */
41327b27ec6Sopenharmony_ci    RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
41427b27ec6Sopenharmony_ci
41527b27ec6Sopenharmony_ci    /* decode-only mode : copy input to @compressedBuffer */
41627b27ec6Sopenharmony_ci    if (g_decodeOnly) {
41727b27ec6Sopenharmony_ci        U32 blockNb;
41827b27ec6Sopenharmony_ci        for (blockNb=0; blockNb < nbBlocks; blockNb++) {
41927b27ec6Sopenharmony_ci            memcpy(blockTable[blockNb].cPtr, blockTable[blockNb].srcPtr, blockTable[blockNb].srcSize);
42027b27ec6Sopenharmony_ci            blockTable[blockNb].cSize = blockTable[blockNb].srcSize;
42127b27ec6Sopenharmony_ci    }   }
42227b27ec6Sopenharmony_ci
42327b27ec6Sopenharmony_ci    /* Bench */
42427b27ec6Sopenharmony_ci    {   U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);
42527b27ec6Sopenharmony_ci        U64 const crcOrig = XXH64(srcBuffer, srcSize, 0);
42627b27ec6Sopenharmony_ci        UTIL_time_t coolTime = UTIL_getTime();
42727b27ec6Sopenharmony_ci        U64 const maxTime = (g_nbSeconds * TIMELOOP_NANOSEC) + 100;
42827b27ec6Sopenharmony_ci        U32 nbCompressionLoops = (U32)((5 MB) / (srcSize+1)) + 1;  /* conservative initial compression speed estimate */
42927b27ec6Sopenharmony_ci        U32 nbDecodeLoops = (U32)((200 MB) / (srcSize+1)) + 1;  /* conservative initial decode speed estimate */
43027b27ec6Sopenharmony_ci        U64 totalCTime=0, totalDTime=0;
43127b27ec6Sopenharmony_ci        U32 cCompleted=(g_decodeOnly==1), dCompleted=0;
43227b27ec6Sopenharmony_ci#       define NB_MARKS 4
43327b27ec6Sopenharmony_ci        const char* const marks[NB_MARKS] = { " |", " /", " =",  "\\" };
43427b27ec6Sopenharmony_ci        U32 markNb = 0;
43527b27ec6Sopenharmony_ci        size_t cSize = srcSize;
43627b27ec6Sopenharmony_ci        size_t totalRSize = srcSize;
43727b27ec6Sopenharmony_ci        double ratio = 0.;
43827b27ec6Sopenharmony_ci
43927b27ec6Sopenharmony_ci        DISPLAYLEVEL(2, "\r%79s\r", "");
44027b27ec6Sopenharmony_ci        while (!cCompleted || !dCompleted) {
44127b27ec6Sopenharmony_ci            /* overheat protection */
44227b27ec6Sopenharmony_ci            if (UTIL_clockSpanMicro(coolTime) > ACTIVEPERIOD_MICROSEC) {
44327b27ec6Sopenharmony_ci                DISPLAYLEVEL(2, "\rcooling down ...    \r");
44427b27ec6Sopenharmony_ci                UTIL_sleep(COOLPERIOD_SEC);
44527b27ec6Sopenharmony_ci                coolTime = UTIL_getTime();
44627b27ec6Sopenharmony_ci            }
44727b27ec6Sopenharmony_ci
44827b27ec6Sopenharmony_ci            /* Compression */
44927b27ec6Sopenharmony_ci            DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (U32)totalRSize);
45027b27ec6Sopenharmony_ci            if (!cCompleted) memset(compressedBuffer, 0xE5, maxCompressedSize);  /* warm up and erase compressed buffer */
45127b27ec6Sopenharmony_ci
45227b27ec6Sopenharmony_ci            UTIL_sleepMilli(1);  /* give processor time to other processes */
45327b27ec6Sopenharmony_ci            UTIL_waitForNextTick();
45427b27ec6Sopenharmony_ci
45527b27ec6Sopenharmony_ci            if (!cCompleted) {   /* still some time to do compression tests */
45627b27ec6Sopenharmony_ci                UTIL_time_t const clockStart = UTIL_getTime();
45727b27ec6Sopenharmony_ci                U32 nbLoops;
45827b27ec6Sopenharmony_ci                for (nbLoops=0; nbLoops < nbCompressionLoops; nbLoops++) {
45927b27ec6Sopenharmony_ci                    U32 blockNb;
46027b27ec6Sopenharmony_ci                    compP.resetFunction(&compP);
46127b27ec6Sopenharmony_ci                    for (blockNb=0; blockNb<nbBlocks; blockNb++) {
46227b27ec6Sopenharmony_ci                        size_t const rSize = (size_t)compP.blockFunction(
46327b27ec6Sopenharmony_ci                            &compP,
46427b27ec6Sopenharmony_ci                            blockTable[blockNb].srcPtr, blockTable[blockNb].cPtr,
46527b27ec6Sopenharmony_ci                            (int)blockTable[blockNb].srcSize, (int)blockTable[blockNb].cRoom);
46627b27ec6Sopenharmony_ci                        if (LZ4_isError(rSize)) END_PROCESS(1, "LZ4 compression failed");
46727b27ec6Sopenharmony_ci                        blockTable[blockNb].cSize = rSize;
46827b27ec6Sopenharmony_ci                }   }
46927b27ec6Sopenharmony_ci                {   U64 const clockSpan = UTIL_clockSpanNano(clockStart);
47027b27ec6Sopenharmony_ci                    if (clockSpan > 0) {
47127b27ec6Sopenharmony_ci                        if (clockSpan < fastestC * nbCompressionLoops)
47227b27ec6Sopenharmony_ci                            fastestC = clockSpan / nbCompressionLoops;
47327b27ec6Sopenharmony_ci                        assert(fastestC > 0);
47427b27ec6Sopenharmony_ci                        nbCompressionLoops = (U32)(TIMELOOP_NANOSEC / fastestC) + 1;  /* aim for ~1sec */
47527b27ec6Sopenharmony_ci                    } else {
47627b27ec6Sopenharmony_ci                        assert(nbCompressionLoops < 40000000);   /* avoid overflow */
47727b27ec6Sopenharmony_ci                        nbCompressionLoops *= 100;
47827b27ec6Sopenharmony_ci                    }
47927b27ec6Sopenharmony_ci                    totalCTime += clockSpan;
48027b27ec6Sopenharmony_ci                    cCompleted = totalCTime>maxTime;
48127b27ec6Sopenharmony_ci                }
48227b27ec6Sopenharmony_ci
48327b27ec6Sopenharmony_ci                cSize = 0;
48427b27ec6Sopenharmony_ci                { U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) cSize += blockTable[blockNb].cSize; }
48527b27ec6Sopenharmony_ci                cSize += !cSize;  /* avoid div by 0 */
48627b27ec6Sopenharmony_ci                ratio = (double)totalRSize / (double)cSize;
48727b27ec6Sopenharmony_ci                markNb = (markNb+1) % NB_MARKS;
48827b27ec6Sopenharmony_ci                DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s\r",
48927b27ec6Sopenharmony_ci                        marks[markNb], displayName,
49027b27ec6Sopenharmony_ci                        (U32)totalRSize, (U32)cSize, ratio,
49127b27ec6Sopenharmony_ci                        ((double)totalRSize / fastestC) * 1000 );
49227b27ec6Sopenharmony_ci            }
49327b27ec6Sopenharmony_ci            (void)fastestD; (void)crcOrig;   /*  unused when decompression disabled */
49427b27ec6Sopenharmony_ci#if 1
49527b27ec6Sopenharmony_ci            /* Decompression */
49627b27ec6Sopenharmony_ci            if (!dCompleted) memset(resultBuffer, 0xD6, srcSize);  /* warm result buffer */
49727b27ec6Sopenharmony_ci
49827b27ec6Sopenharmony_ci            UTIL_sleepMilli(5); /* give processor time to other processes */
49927b27ec6Sopenharmony_ci            UTIL_waitForNextTick();
50027b27ec6Sopenharmony_ci
50127b27ec6Sopenharmony_ci            if (!dCompleted) {
50227b27ec6Sopenharmony_ci                const DecFunction_f decFunction = g_decodeOnly ?
50327b27ec6Sopenharmony_ci                    LZ4F_decompress_binding : LZ4_decompress_safe_usingDict;
50427b27ec6Sopenharmony_ci                const char* const decString = g_decodeOnly ?
50527b27ec6Sopenharmony_ci                    "LZ4F_decompress" : "LZ4_decompress_safe_usingDict";
50627b27ec6Sopenharmony_ci                UTIL_time_t const clockStart = UTIL_getTime();
50727b27ec6Sopenharmony_ci                U32 nbLoops;
50827b27ec6Sopenharmony_ci
50927b27ec6Sopenharmony_ci                for (nbLoops=0; nbLoops < nbDecodeLoops; nbLoops++) {
51027b27ec6Sopenharmony_ci                    U32 blockNb;
51127b27ec6Sopenharmony_ci                    for (blockNb=0; blockNb<nbBlocks; blockNb++) {
51227b27ec6Sopenharmony_ci                        size_t const inMaxSize = (size_t)INT_MAX / decMultiplier;
51327b27ec6Sopenharmony_ci                        size_t const resCapa = (blockTable[blockNb].srcSize < inMaxSize) ?
51427b27ec6Sopenharmony_ci                                                blockTable[blockNb].srcSize * decMultiplier :
51527b27ec6Sopenharmony_ci                                                INT_MAX;
51627b27ec6Sopenharmony_ci                        int const regenSize = decFunction(
51727b27ec6Sopenharmony_ci                            blockTable[blockNb].cPtr, blockTable[blockNb].resPtr,
51827b27ec6Sopenharmony_ci                            (int)blockTable[blockNb].cSize, (int)resCapa,
51927b27ec6Sopenharmony_ci                            dictBuf, dictSize);
52027b27ec6Sopenharmony_ci                        if (regenSize < 0) {
52127b27ec6Sopenharmony_ci                            DISPLAY("%s() failed on block %u of size %u \n",
52227b27ec6Sopenharmony_ci                                decString, blockNb, (unsigned)blockTable[blockNb].srcSize);
52327b27ec6Sopenharmony_ci                            if (g_decodeOnly)
52427b27ec6Sopenharmony_ci                                DISPLAY("Is input using LZ4 Frame format ? \n");
52527b27ec6Sopenharmony_ci                            END_PROCESS(2, "error during decoding");
52627b27ec6Sopenharmony_ci                            break;
52727b27ec6Sopenharmony_ci                        }
52827b27ec6Sopenharmony_ci                        blockTable[blockNb].resSize = (size_t)regenSize;
52927b27ec6Sopenharmony_ci                }   }
53027b27ec6Sopenharmony_ci                {   U64 const clockSpan = UTIL_clockSpanNano(clockStart);
53127b27ec6Sopenharmony_ci                    if (clockSpan > 0) {
53227b27ec6Sopenharmony_ci                        if (clockSpan < fastestD * nbDecodeLoops)
53327b27ec6Sopenharmony_ci                            fastestD = clockSpan / nbDecodeLoops;
53427b27ec6Sopenharmony_ci                        assert(fastestD > 0);
53527b27ec6Sopenharmony_ci                        nbDecodeLoops = (U32)(TIMELOOP_NANOSEC / fastestD) + 1;  /* aim for ~1sec */
53627b27ec6Sopenharmony_ci                    } else {
53727b27ec6Sopenharmony_ci                        assert(nbDecodeLoops < 40000000);   /* avoid overflow */
53827b27ec6Sopenharmony_ci                        nbDecodeLoops *= 100;
53927b27ec6Sopenharmony_ci                    }
54027b27ec6Sopenharmony_ci                    totalDTime += clockSpan;
54127b27ec6Sopenharmony_ci                    dCompleted = totalDTime > (DECOMP_MULT*maxTime);
54227b27ec6Sopenharmony_ci            }   }
54327b27ec6Sopenharmony_ci
54427b27ec6Sopenharmony_ci            if (g_decodeOnly) {
54527b27ec6Sopenharmony_ci                unsigned u;
54627b27ec6Sopenharmony_ci                totalRSize = 0;
54727b27ec6Sopenharmony_ci                for (u=0; u<nbBlocks; u++) totalRSize += blockTable[u].resSize;
54827b27ec6Sopenharmony_ci            }
54927b27ec6Sopenharmony_ci            markNb = (markNb+1) % NB_MARKS;
55027b27ec6Sopenharmony_ci            ratio  = (double)totalRSize / (double)cSize;
55127b27ec6Sopenharmony_ci            DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s ,%6.1f MB/s\r",
55227b27ec6Sopenharmony_ci                    marks[markNb], displayName,
55327b27ec6Sopenharmony_ci                    (U32)totalRSize, (U32)cSize, ratio,
55427b27ec6Sopenharmony_ci                    ((double)totalRSize / fastestC) * 1000,
55527b27ec6Sopenharmony_ci                    ((double)totalRSize / fastestD) * 1000);
55627b27ec6Sopenharmony_ci
55727b27ec6Sopenharmony_ci            /* CRC Checking (not possible in decode-only mode)*/
55827b27ec6Sopenharmony_ci            if (!g_decodeOnly) {
55927b27ec6Sopenharmony_ci                U64 const crcCheck = XXH64(resultBuffer, srcSize, 0);
56027b27ec6Sopenharmony_ci                if (crcOrig!=crcCheck) {
56127b27ec6Sopenharmony_ci                    size_t u;
56227b27ec6Sopenharmony_ci                    DISPLAY("\n!!! WARNING !!! %17s : Invalid Checksum : %x != %x   \n", displayName, (unsigned)crcOrig, (unsigned)crcCheck);
56327b27ec6Sopenharmony_ci                    for (u=0; u<srcSize; u++) {
56427b27ec6Sopenharmony_ci                        if (((const BYTE*)srcBuffer)[u] != ((const BYTE*)resultBuffer)[u]) {
56527b27ec6Sopenharmony_ci                            U32 segNb, bNb, pos;
56627b27ec6Sopenharmony_ci                            size_t bacc = 0;
56727b27ec6Sopenharmony_ci                            DISPLAY("Decoding error at pos %u ", (U32)u);
56827b27ec6Sopenharmony_ci                            for (segNb = 0; segNb < nbBlocks; segNb++) {
56927b27ec6Sopenharmony_ci                                if (bacc + blockTable[segNb].srcSize > u) break;
57027b27ec6Sopenharmony_ci                                bacc += blockTable[segNb].srcSize;
57127b27ec6Sopenharmony_ci                            }
57227b27ec6Sopenharmony_ci                            pos = (U32)(u - bacc);
57327b27ec6Sopenharmony_ci                            bNb = pos / (128 KB);
57427b27ec6Sopenharmony_ci                            DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
57527b27ec6Sopenharmony_ci                            break;
57627b27ec6Sopenharmony_ci                        }
57727b27ec6Sopenharmony_ci                        if (u==srcSize-1) {  /* should never happen */
57827b27ec6Sopenharmony_ci                            DISPLAY("no difference detected\n");
57927b27ec6Sopenharmony_ci                    }   }
58027b27ec6Sopenharmony_ci                    break;
58127b27ec6Sopenharmony_ci            }   }   /* CRC Checking */
58227b27ec6Sopenharmony_ci#endif
58327b27ec6Sopenharmony_ci        }   /* for (testNb = 1; testNb <= (g_nbSeconds + !g_nbSeconds); testNb++) */
58427b27ec6Sopenharmony_ci
58527b27ec6Sopenharmony_ci        if (g_displayLevel == 1) {
58627b27ec6Sopenharmony_ci            double const cSpeed = ((double)srcSize / fastestC) * 1000;
58727b27ec6Sopenharmony_ci            double const dSpeed = ((double)srcSize / fastestD) * 1000;
58827b27ec6Sopenharmony_ci            if (g_additionalParam)
58927b27ec6Sopenharmony_ci                DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s (param=%d)\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName, g_additionalParam);
59027b27ec6Sopenharmony_ci            else
59127b27ec6Sopenharmony_ci                DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s  %s\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName);
59227b27ec6Sopenharmony_ci        }
59327b27ec6Sopenharmony_ci        DISPLAYLEVEL(2, "%2i#\n", cLevel);
59427b27ec6Sopenharmony_ci    }   /* Bench */
59527b27ec6Sopenharmony_ci
59627b27ec6Sopenharmony_ci    /* clean up */
59727b27ec6Sopenharmony_ci    compP.cleanupFunction(&compP);
59827b27ec6Sopenharmony_ci    free(blockTable);
59927b27ec6Sopenharmony_ci    free(compressedBuffer);
60027b27ec6Sopenharmony_ci    free(resultBuffer);
60127b27ec6Sopenharmony_ci    return 0;
60227b27ec6Sopenharmony_ci}
60327b27ec6Sopenharmony_ci
60427b27ec6Sopenharmony_ci
60527b27ec6Sopenharmony_cistatic size_t BMK_findMaxMem(U64 requiredMem)
60627b27ec6Sopenharmony_ci{
60727b27ec6Sopenharmony_ci    size_t step = 64 MB;
60827b27ec6Sopenharmony_ci    BYTE* testmem=NULL;
60927b27ec6Sopenharmony_ci
61027b27ec6Sopenharmony_ci    requiredMem = (((requiredMem >> 26) + 1) << 26);
61127b27ec6Sopenharmony_ci    requiredMem += 2*step;
61227b27ec6Sopenharmony_ci    if (requiredMem > maxMemory) requiredMem = maxMemory;
61327b27ec6Sopenharmony_ci
61427b27ec6Sopenharmony_ci    while (!testmem) {
61527b27ec6Sopenharmony_ci        if (requiredMem > step) requiredMem -= step;
61627b27ec6Sopenharmony_ci        else requiredMem >>= 1;
61727b27ec6Sopenharmony_ci        testmem = (BYTE*) malloc ((size_t)requiredMem);
61827b27ec6Sopenharmony_ci    }
61927b27ec6Sopenharmony_ci    free (testmem);
62027b27ec6Sopenharmony_ci
62127b27ec6Sopenharmony_ci    /* keep some space available */
62227b27ec6Sopenharmony_ci    if (requiredMem > step) requiredMem -= step;
62327b27ec6Sopenharmony_ci    else requiredMem >>= 1;
62427b27ec6Sopenharmony_ci
62527b27ec6Sopenharmony_ci    return (size_t)requiredMem;
62627b27ec6Sopenharmony_ci}
62727b27ec6Sopenharmony_ci
62827b27ec6Sopenharmony_ci
62927b27ec6Sopenharmony_cistatic void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
63027b27ec6Sopenharmony_ci                            const char* displayName, int cLevel, int cLevelLast,
63127b27ec6Sopenharmony_ci                            const size_t* fileSizes, unsigned nbFiles,
63227b27ec6Sopenharmony_ci                            const char* dictBuf, int dictSize)
63327b27ec6Sopenharmony_ci{
63427b27ec6Sopenharmony_ci    int l;
63527b27ec6Sopenharmony_ci
63627b27ec6Sopenharmony_ci    const char* pch = strrchr(displayName, '\\'); /* Windows */
63727b27ec6Sopenharmony_ci    if (!pch) pch = strrchr(displayName, '/'); /* Linux */
63827b27ec6Sopenharmony_ci    if (pch) displayName = pch+1;
63927b27ec6Sopenharmony_ci
64027b27ec6Sopenharmony_ci    SET_REALTIME_PRIORITY;
64127b27ec6Sopenharmony_ci
64227b27ec6Sopenharmony_ci    if (g_displayLevel == 1 && !g_additionalParam)
64327b27ec6Sopenharmony_ci        DISPLAY("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n", LZ4_VERSION_STRING, LZ4_GIT_COMMIT_STRING, (U32)benchedSize, g_nbSeconds, (U32)(g_blockSize>>10));
64427b27ec6Sopenharmony_ci
64527b27ec6Sopenharmony_ci    if (cLevelLast < cLevel) cLevelLast = cLevel;
64627b27ec6Sopenharmony_ci
64727b27ec6Sopenharmony_ci    for (l=cLevel; l <= cLevelLast; l++) {
64827b27ec6Sopenharmony_ci        BMK_benchMem(srcBuffer, benchedSize,
64927b27ec6Sopenharmony_ci                     displayName, l,
65027b27ec6Sopenharmony_ci                     fileSizes, nbFiles,
65127b27ec6Sopenharmony_ci                     dictBuf, dictSize);
65227b27ec6Sopenharmony_ci    }
65327b27ec6Sopenharmony_ci}
65427b27ec6Sopenharmony_ci
65527b27ec6Sopenharmony_ci
65627b27ec6Sopenharmony_ci/*! BMK_loadFiles() :
65727b27ec6Sopenharmony_ci    Loads `buffer` with content of files listed within `fileNamesTable`.
65827b27ec6Sopenharmony_ci    At most, fills `buffer` entirely */
65927b27ec6Sopenharmony_cistatic void BMK_loadFiles(void* buffer, size_t bufferSize,
66027b27ec6Sopenharmony_ci                          size_t* fileSizes,
66127b27ec6Sopenharmony_ci                          const char** fileNamesTable, unsigned nbFiles)
66227b27ec6Sopenharmony_ci{
66327b27ec6Sopenharmony_ci    size_t pos = 0, totalSize = 0;
66427b27ec6Sopenharmony_ci    unsigned n;
66527b27ec6Sopenharmony_ci    for (n=0; n<nbFiles; n++) {
66627b27ec6Sopenharmony_ci        FILE* f;
66727b27ec6Sopenharmony_ci        U64 fileSize = UTIL_getFileSize(fileNamesTable[n]);
66827b27ec6Sopenharmony_ci        if (UTIL_isDirectory(fileNamesTable[n])) {
66927b27ec6Sopenharmony_ci            DISPLAYLEVEL(2, "Ignoring %s directory...       \n", fileNamesTable[n]);
67027b27ec6Sopenharmony_ci            fileSizes[n] = 0;
67127b27ec6Sopenharmony_ci            continue;
67227b27ec6Sopenharmony_ci        }
67327b27ec6Sopenharmony_ci        f = fopen(fileNamesTable[n], "rb");
67427b27ec6Sopenharmony_ci        if (f==NULL) END_PROCESS(10, "impossible to open file %s", fileNamesTable[n]);
67527b27ec6Sopenharmony_ci        DISPLAYUPDATE(2, "Loading %s...       \r", fileNamesTable[n]);
67627b27ec6Sopenharmony_ci        if (fileSize > bufferSize-pos) { /* buffer too small - stop after this file */
67727b27ec6Sopenharmony_ci            fileSize = bufferSize-pos;
67827b27ec6Sopenharmony_ci            nbFiles=n;
67927b27ec6Sopenharmony_ci        }
68027b27ec6Sopenharmony_ci        { size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);
68127b27ec6Sopenharmony_ci          if (readSize != (size_t)fileSize) END_PROCESS(11, "could not read %s", fileNamesTable[n]);
68227b27ec6Sopenharmony_ci          pos += readSize; }
68327b27ec6Sopenharmony_ci        fileSizes[n] = (size_t)fileSize;
68427b27ec6Sopenharmony_ci        totalSize += (size_t)fileSize;
68527b27ec6Sopenharmony_ci        fclose(f);
68627b27ec6Sopenharmony_ci    }
68727b27ec6Sopenharmony_ci
68827b27ec6Sopenharmony_ci    if (totalSize == 0) END_PROCESS(12, "no data to bench");
68927b27ec6Sopenharmony_ci}
69027b27ec6Sopenharmony_ci
69127b27ec6Sopenharmony_cistatic void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
69227b27ec6Sopenharmony_ci                               int cLevel, int cLevelLast,
69327b27ec6Sopenharmony_ci                               const char* dictBuf, int dictSize)
69427b27ec6Sopenharmony_ci{
69527b27ec6Sopenharmony_ci    void* srcBuffer;
69627b27ec6Sopenharmony_ci    size_t benchedSize;
69727b27ec6Sopenharmony_ci    size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
69827b27ec6Sopenharmony_ci    U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles);
69927b27ec6Sopenharmony_ci    char mfName[20] = {0};
70027b27ec6Sopenharmony_ci
70127b27ec6Sopenharmony_ci    if (!fileSizes) END_PROCESS(12, "not enough memory for fileSizes");
70227b27ec6Sopenharmony_ci
70327b27ec6Sopenharmony_ci    /* Memory allocation & restrictions */
70427b27ec6Sopenharmony_ci    benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3;
70527b27ec6Sopenharmony_ci    if (benchedSize==0) END_PROCESS(12, "not enough memory");
70627b27ec6Sopenharmony_ci    if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;
70727b27ec6Sopenharmony_ci    if (benchedSize > LZ4_MAX_INPUT_SIZE) {
70827b27ec6Sopenharmony_ci        benchedSize = LZ4_MAX_INPUT_SIZE;
70927b27ec6Sopenharmony_ci        DISPLAY("File(s) bigger than LZ4's max input size; testing %u MB only...\n", (U32)(benchedSize >> 20));
71027b27ec6Sopenharmony_ci    } else {
71127b27ec6Sopenharmony_ci        if (benchedSize < totalSizeToLoad)
71227b27ec6Sopenharmony_ci            DISPLAY("Not enough memory; testing %u MB only...\n", (U32)(benchedSize >> 20));
71327b27ec6Sopenharmony_ci    }
71427b27ec6Sopenharmony_ci    srcBuffer = malloc(benchedSize + !benchedSize);   /* avoid alloc of zero */
71527b27ec6Sopenharmony_ci    if (!srcBuffer) END_PROCESS(12, "not enough memory");
71627b27ec6Sopenharmony_ci
71727b27ec6Sopenharmony_ci    /* Load input buffer */
71827b27ec6Sopenharmony_ci    BMK_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles);
71927b27ec6Sopenharmony_ci
72027b27ec6Sopenharmony_ci    /* Bench */
72127b27ec6Sopenharmony_ci    snprintf (mfName, sizeof(mfName), " %u files", nbFiles);
72227b27ec6Sopenharmony_ci    {   const char* displayName = (nbFiles > 1) ? mfName : fileNamesTable[0];
72327b27ec6Sopenharmony_ci        BMK_benchCLevel(srcBuffer, benchedSize,
72427b27ec6Sopenharmony_ci                        displayName, cLevel, cLevelLast,
72527b27ec6Sopenharmony_ci                        fileSizes, nbFiles,
72627b27ec6Sopenharmony_ci                        dictBuf, dictSize);
72727b27ec6Sopenharmony_ci    }
72827b27ec6Sopenharmony_ci
72927b27ec6Sopenharmony_ci    /* clean up */
73027b27ec6Sopenharmony_ci    free(srcBuffer);
73127b27ec6Sopenharmony_ci    free(fileSizes);
73227b27ec6Sopenharmony_ci}
73327b27ec6Sopenharmony_ci
73427b27ec6Sopenharmony_ci
73527b27ec6Sopenharmony_cistatic void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility,
73627b27ec6Sopenharmony_ci                              const char* dictBuf, int dictSize)
73727b27ec6Sopenharmony_ci{
73827b27ec6Sopenharmony_ci    char name[20] = {0};
73927b27ec6Sopenharmony_ci    size_t benchedSize = 10000000;
74027b27ec6Sopenharmony_ci    void* const srcBuffer = malloc(benchedSize);
74127b27ec6Sopenharmony_ci
74227b27ec6Sopenharmony_ci    /* Memory allocation */
74327b27ec6Sopenharmony_ci    if (!srcBuffer) END_PROCESS(21, "not enough memory");
74427b27ec6Sopenharmony_ci
74527b27ec6Sopenharmony_ci    /* Fill input buffer */
74627b27ec6Sopenharmony_ci    RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0);
74727b27ec6Sopenharmony_ci
74827b27ec6Sopenharmony_ci    /* Bench */
74927b27ec6Sopenharmony_ci    snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100));
75027b27ec6Sopenharmony_ci    BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, dictBuf, dictSize);
75127b27ec6Sopenharmony_ci
75227b27ec6Sopenharmony_ci    /* clean up */
75327b27ec6Sopenharmony_ci    free(srcBuffer);
75427b27ec6Sopenharmony_ci}
75527b27ec6Sopenharmony_ci
75627b27ec6Sopenharmony_ci
75727b27ec6Sopenharmony_cistatic int
75827b27ec6Sopenharmony_ciBMK_benchFilesSeparately(const char** fileNamesTable, unsigned nbFiles,
75927b27ec6Sopenharmony_ci                   int cLevel, int cLevelLast,
76027b27ec6Sopenharmony_ci                   const char* dictBuf, int dictSize)
76127b27ec6Sopenharmony_ci{
76227b27ec6Sopenharmony_ci    unsigned fileNb;
76327b27ec6Sopenharmony_ci    if (cLevel > LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX;
76427b27ec6Sopenharmony_ci    if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX;
76527b27ec6Sopenharmony_ci    if (cLevelLast < cLevel) cLevelLast = cLevel;
76627b27ec6Sopenharmony_ci
76727b27ec6Sopenharmony_ci    for (fileNb=0; fileNb<nbFiles; fileNb++)
76827b27ec6Sopenharmony_ci        BMK_benchFileTable(fileNamesTable+fileNb, 1, cLevel, cLevelLast, dictBuf, dictSize);
76927b27ec6Sopenharmony_ci
77027b27ec6Sopenharmony_ci    return 0;
77127b27ec6Sopenharmony_ci}
77227b27ec6Sopenharmony_ci
77327b27ec6Sopenharmony_ci
77427b27ec6Sopenharmony_ciint BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
77527b27ec6Sopenharmony_ci                   int cLevel, int cLevelLast,
77627b27ec6Sopenharmony_ci                   const char* dictFileName)
77727b27ec6Sopenharmony_ci{
77827b27ec6Sopenharmony_ci    double const compressibility = (double)g_compressibilityDefault / 100;
77927b27ec6Sopenharmony_ci    char* dictBuf = NULL;
78027b27ec6Sopenharmony_ci    size_t dictSize = 0;
78127b27ec6Sopenharmony_ci
78227b27ec6Sopenharmony_ci    if (cLevel > LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX;
78327b27ec6Sopenharmony_ci    if (g_decodeOnly) {
78427b27ec6Sopenharmony_ci        DISPLAYLEVEL(2, "Benchmark Decompression of LZ4 Frame ");
78527b27ec6Sopenharmony_ci        if (g_skipChecksums) {
78627b27ec6Sopenharmony_ci            DISPLAYLEVEL(2, "_without_ checksum even when present \n");
78727b27ec6Sopenharmony_ci        } else {
78827b27ec6Sopenharmony_ci            DISPLAYLEVEL(2, "+ Checksum when present \n");
78927b27ec6Sopenharmony_ci        }
79027b27ec6Sopenharmony_ci        cLevelLast = cLevel;
79127b27ec6Sopenharmony_ci    }
79227b27ec6Sopenharmony_ci    if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX;
79327b27ec6Sopenharmony_ci    if (cLevelLast < cLevel) cLevelLast = cLevel;
79427b27ec6Sopenharmony_ci    if (cLevelLast > cLevel)
79527b27ec6Sopenharmony_ci        DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
79627b27ec6Sopenharmony_ci
79727b27ec6Sopenharmony_ci    if (dictFileName) {
79827b27ec6Sopenharmony_ci        FILE* dictFile = NULL;
79927b27ec6Sopenharmony_ci        U64 const dictFileSize = UTIL_getFileSize(dictFileName);
80027b27ec6Sopenharmony_ci        if (!dictFileSize)
80127b27ec6Sopenharmony_ci            END_PROCESS(25, "Dictionary error : could not stat dictionary file");
80227b27ec6Sopenharmony_ci        if (g_decodeOnly)
80327b27ec6Sopenharmony_ci            END_PROCESS(26, "Error : LZ4 Frame decoder mode not compatible with dictionary yet");
80427b27ec6Sopenharmony_ci
80527b27ec6Sopenharmony_ci        dictFile = fopen(dictFileName, "rb");
80627b27ec6Sopenharmony_ci        if (!dictFile)
80727b27ec6Sopenharmony_ci            END_PROCESS(25, "Dictionary error : could not open dictionary file");
80827b27ec6Sopenharmony_ci
80927b27ec6Sopenharmony_ci        if (dictFileSize > LZ4_MAX_DICT_SIZE) {
81027b27ec6Sopenharmony_ci            dictSize = LZ4_MAX_DICT_SIZE;
81127b27ec6Sopenharmony_ci            if (UTIL_fseek(dictFile, (long)(dictFileSize - dictSize), SEEK_SET))
81227b27ec6Sopenharmony_ci                END_PROCESS(25, "Dictionary error : could not seek dictionary file");
81327b27ec6Sopenharmony_ci        } else {
81427b27ec6Sopenharmony_ci            dictSize = (size_t)dictFileSize;
81527b27ec6Sopenharmony_ci        }
81627b27ec6Sopenharmony_ci
81727b27ec6Sopenharmony_ci        dictBuf = (char*)malloc(dictSize);
81827b27ec6Sopenharmony_ci        if (!dictBuf) END_PROCESS(25, "Allocation error : not enough memory");
81927b27ec6Sopenharmony_ci
82027b27ec6Sopenharmony_ci        if (fread(dictBuf, 1, dictSize, dictFile) != dictSize)
82127b27ec6Sopenharmony_ci            END_PROCESS(25, "Dictionary error : could not read dictionary file");
82227b27ec6Sopenharmony_ci
82327b27ec6Sopenharmony_ci        fclose(dictFile);
82427b27ec6Sopenharmony_ci    }
82527b27ec6Sopenharmony_ci
82627b27ec6Sopenharmony_ci    if (nbFiles == 0)
82727b27ec6Sopenharmony_ci        BMK_syntheticTest(cLevel, cLevelLast, compressibility, dictBuf, (int)dictSize);
82827b27ec6Sopenharmony_ci    else {
82927b27ec6Sopenharmony_ci        if (g_benchSeparately)
83027b27ec6Sopenharmony_ci            BMK_benchFilesSeparately(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, (int)dictSize);
83127b27ec6Sopenharmony_ci        else
83227b27ec6Sopenharmony_ci            BMK_benchFileTable(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, (int)dictSize);
83327b27ec6Sopenharmony_ci    }
83427b27ec6Sopenharmony_ci
83527b27ec6Sopenharmony_ci    free(dictBuf);
83627b27ec6Sopenharmony_ci    return 0;
83727b27ec6Sopenharmony_ci}
838