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