| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 1 | /* |
| 2 | bench.c - Demo module to benchmark open-source compression algorithms |
| 3 | Copyright (C) Yann Collet 2012-2015 |
| 4 | |
| 5 | GPL v2 License |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 2 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License along |
| 18 | with this program; if not, write to the Free Software Foundation, Inc., |
| 19 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | |
| 21 | You can contact the author at : |
| 22 | - zstd source repository : https://github.com/Cyan4973/zstd |
| 23 | - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c |
| 24 | */ |
| 25 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 26 | /* ************************************** |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 27 | * Compiler Options |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 28 | ****************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 29 | /* Disable some Visual warning messages */ |
| 30 | #define _CRT_SECURE_NO_WARNINGS /* fopen */ |
| 31 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 32 | /* Unix Large Files support (>4GB) */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 33 | #define _FILE_OFFSET_BITS 64 |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 34 | #if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 35 | # define _LARGEFILE_SOURCE |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 36 | #elif ! defined(__LP64__) /* No point defining Large file for 64 bit */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 37 | # define _LARGEFILE64_SOURCE |
| 38 | #endif |
| 39 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 40 | /* S_ISREG & gettimeofday() are not supported by MSVC */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 41 | #if defined(_MSC_VER) || defined(_WIN32) |
| 42 | # define BMK_LEGACY_TIMER 1 |
| 43 | #endif |
| 44 | |
| 45 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 46 | /* ************************************* |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 47 | * Includes |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 48 | ***************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 49 | #include <stdlib.h> /* malloc, free */ |
| 50 | #include <string.h> /* memset */ |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 51 | #include <stdio.h> /* fprintf, fopen, ftello64 */ |
| 52 | #include <sys/types.h> /* stat64 */ |
| 53 | #include <sys/stat.h> /* stat64 */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 54 | |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 55 | /* Use ftime() if gettimeofday() is not available */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 56 | #if defined(BMK_LEGACY_TIMER) |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 57 | # include <sys/timeb.h> /* timeb, ftime */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 58 | #else |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 59 | # include <sys/time.h> /* gettimeofday */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 60 | #endif |
| 61 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 62 | #include "mem.h" |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 63 | #include "zstd.h" |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 64 | #include "zstdhc.h" |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 65 | #include "xxhash.h" |
| 66 | |
| 67 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 68 | /* ************************************* |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 69 | * Compiler specifics |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 70 | ***************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 71 | #if !defined(S_ISREG) |
| 72 | # define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) |
| 73 | #endif |
| 74 | |
| 75 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 76 | /* ************************************* |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 77 | * Constants |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 78 | ***************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 79 | #define NBLOOPS 3 |
| 80 | #define TIMELOOP 2500 |
| 81 | |
| 82 | #define KB *(1 <<10) |
| 83 | #define MB *(1 <<20) |
| 84 | #define GB *(1U<<30) |
| 85 | |
| Yann Collet | 050efba | 2015-11-03 09:49:30 +0100 | [diff] [blame^] | 86 | static const size_t maxMemory = sizeof(size_t)==4 ? (2 GB - 64 MB) : 8ULL GB; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 87 | #define DEFAULT_CHUNKSIZE (4 MB) |
| 88 | |
| 89 | static U32 g_compressibilityDefault = 50; |
| 90 | static U32 prime1 = 2654435761U; |
| 91 | static U32 prime2 = 2246822519U; |
| 92 | |
| 93 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 94 | /* ************************************* |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 95 | * Macros |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 96 | ***************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 97 | #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) |
| 98 | |
| 99 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 100 | /* ************************************* |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 101 | * Benchmark Parameters |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 102 | ***************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 103 | static int nbIterations = NBLOOPS; |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 104 | static size_t g_blockSize = 0; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 105 | |
| 106 | void BMK_SetNbIterations(int nbLoops) |
| 107 | { |
| 108 | nbIterations = nbLoops; |
| 109 | DISPLAY("- %i iterations -\n", nbIterations); |
| 110 | } |
| 111 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 112 | void BMK_SetBlockSize(size_t blockSize) |
| 113 | { |
| 114 | g_blockSize = blockSize; |
| 115 | DISPLAY("using blocks of size %u KB \n", (U32)(blockSize>>10)); |
| 116 | } |
| 117 | |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 118 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 119 | /* ******************************************************** |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 120 | * Private functions |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 121 | **********************************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 122 | |
| 123 | #if defined(BMK_LEGACY_TIMER) |
| 124 | |
| 125 | static int BMK_GetMilliStart(void) |
| 126 | { |
| 127 | /* Based on Legacy ftime() |
| 128 | * Rolls over every ~ 12.1 days (0x100000/24/60/60) |
| 129 | * Use GetMilliSpan to correct for rollover */ |
| 130 | struct timeb tb; |
| 131 | int nCount; |
| 132 | ftime( &tb ); |
| 133 | nCount = (int) (tb.millitm + (tb.time & 0xfffff) * 1000); |
| 134 | return nCount; |
| 135 | } |
| 136 | |
| 137 | #else |
| 138 | |
| 139 | static int BMK_GetMilliStart(void) |
| 140 | { |
| 141 | /* Based on newer gettimeofday() |
| 142 | * Use GetMilliSpan to correct for rollover */ |
| 143 | struct timeval tv; |
| 144 | int nCount; |
| 145 | gettimeofday(&tv, NULL); |
| 146 | nCount = (int) (tv.tv_usec/1000 + (tv.tv_sec & 0xfffff) * 1000); |
| 147 | return nCount; |
| 148 | } |
| 149 | |
| 150 | #endif |
| 151 | |
| 152 | |
| 153 | static int BMK_GetMilliSpan( int nTimeStart ) |
| 154 | { |
| 155 | int nSpan = BMK_GetMilliStart() - nTimeStart; |
| 156 | if ( nSpan < 0 ) |
| 157 | nSpan += 0x100000 * 1000; |
| 158 | return nSpan; |
| 159 | } |
| 160 | |
| 161 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 162 | /* ******************************************************** |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 163 | * Data generator |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 164 | **********************************************************/ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 165 | /* will hopefully be converted into ROL instruction by compiler */ |
| 166 | static U32 BMK_rotl32(unsigned val32, unsigned nbBits) { return((val32 << nbBits) | (val32 >> (32 - nbBits))); } |
| 167 | |
| 168 | static U32 BMK_rand(U32* src) |
| 169 | { |
| 170 | U32 rand32 = *src; |
| 171 | rand32 *= prime1; |
| 172 | rand32 += prime2; |
| 173 | rand32 = BMK_rotl32(rand32, 13); |
| 174 | *src = rand32; |
| 175 | return rand32 >> 9; |
| 176 | } |
| 177 | |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 178 | #define BMK_RAND15BITS ( BMK_rand(&seed) & 0x7FFF) |
| 179 | #define BMK_RANDLENGTH ((BMK_rand(&seed) & 3) ? (BMK_rand(&seed) % 15) : (BMK_rand(&seed) % 510) + 15) |
| 180 | #define BMK_RANDCHAR (BYTE)((BMK_rand(&seed) & 63) + '0') |
| 181 | static void BMK_datagen(void* buffer, size_t bufferSize, double proba, U32 seed) |
| 182 | { |
| 183 | BYTE* BBuffer = (BYTE*)buffer; |
| 184 | unsigned pos = 0; |
| 185 | U32 P32 = (U32)(32768 * proba); |
| 186 | |
| 187 | /* First Byte */ |
| 188 | BBuffer[pos++] = BMK_RANDCHAR; |
| 189 | |
| 190 | while (pos < bufferSize) |
| 191 | { |
| 192 | /* Select : Literal (noise) or copy (within 64K) */ |
| 193 | if (BMK_RAND15BITS < P32) |
| 194 | { |
| 195 | /* Match */ |
| 196 | size_t match, end; |
| 197 | unsigned length = BMK_RANDLENGTH + 4; |
| 198 | unsigned offset = BMK_RAND15BITS + 1; |
| 199 | if (offset > pos) offset = pos; |
| 200 | match = pos - offset; |
| 201 | end = pos + length; |
| 202 | if (end > bufferSize) end = bufferSize; |
| 203 | while (pos < end) BBuffer[pos++] = BBuffer[match++]; |
| 204 | } |
| 205 | else |
| 206 | { |
| 207 | /* Literal */ |
| 208 | size_t end; |
| 209 | unsigned length = BMK_RANDLENGTH; |
| 210 | end = pos + length; |
| 211 | if (end > bufferSize) end = bufferSize; |
| 212 | while (pos < end) BBuffer[pos++] = BMK_RANDCHAR; |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 218 | /* ******************************************************** |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 219 | * Bench functions |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 220 | **********************************************************/ |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 221 | typedef struct |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 222 | { |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 223 | char* srcPtr; |
| 224 | size_t srcSize; |
| 225 | char* cPtr; |
| 226 | size_t cRoom; |
| 227 | size_t cSize; |
| 228 | char* resPtr; |
| 229 | size_t resSize; |
| 230 | } blockParam_t; |
| 231 | |
| Yann Collet | 2acb5d3 | 2015-10-29 16:49:43 +0100 | [diff] [blame] | 232 | typedef size_t (*compressor_t) (void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel); |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 233 | |
| Yann Collet | 2acb5d3 | 2015-10-29 16:49:43 +0100 | [diff] [blame] | 234 | static size_t local_compress_fast (void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel) |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 235 | { |
| 236 | (void)compressionLevel; |
| 237 | return ZSTD_compress(dst, maxDstSize, src, srcSize); |
| 238 | } |
| 239 | |
| Yann Collet | be2010e | 2015-10-31 12:57:14 +0100 | [diff] [blame] | 240 | #define MIN(a,b) ((a)<(b) ? (a) : (b)) |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 241 | |
| 242 | static int BMK_benchMem(void* srcBuffer, size_t srcSize, const char* fileName, int cLevel) |
| 243 | { |
| 244 | const size_t blockSize = g_blockSize ? g_blockSize : srcSize; |
| 245 | const U32 nbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize); |
| 246 | blockParam_t* const blockTable = (blockParam_t*) malloc(nbBlocks * sizeof(blockParam_t)); |
| 247 | const size_t maxCompressedSize = (size_t)nbBlocks * ZSTD_compressBound(blockSize); |
| 248 | void* const compressedBuffer = malloc(maxCompressedSize); |
| 249 | void* const resultBuffer = malloc(srcSize); |
| Yann Collet | c776c46 | 2015-10-29 19:10:54 +0100 | [diff] [blame] | 250 | const compressor_t compressor = (cLevel <= 1) ? local_compress_fast : ZSTD_HC_compress; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 251 | U64 crcOrig; |
| 252 | |
| Yann Collet | c776c46 | 2015-10-29 19:10:54 +0100 | [diff] [blame] | 253 | /* init */ |
| 254 | if (strlen(fileName)>16) |
| 255 | fileName += strlen(fileName)-16; |
| 256 | |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 257 | /* Memory allocation & restrictions */ |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 258 | if (!compressedBuffer || !resultBuffer || !blockTable) |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 259 | { |
| 260 | DISPLAY("\nError: not enough memory!\n"); |
| 261 | free(compressedBuffer); |
| 262 | free(resultBuffer); |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 263 | free(blockTable); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 264 | return 12; |
| 265 | } |
| 266 | |
| 267 | /* Calculating input Checksum */ |
| 268 | crcOrig = XXH64(srcBuffer, srcSize, 0); |
| 269 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 270 | /* Init blockTable data */ |
| 271 | { |
| 272 | U32 i; |
| 273 | size_t remaining = srcSize; |
| 274 | char* srcPtr = (char*)srcBuffer; |
| 275 | char* cPtr = (char*)compressedBuffer; |
| 276 | char* resPtr = (char*)resultBuffer; |
| 277 | for (i=0; i<nbBlocks; i++) |
| 278 | { |
| 279 | size_t thisBlockSize = MIN(remaining, blockSize); |
| 280 | blockTable[i].srcPtr = srcPtr; |
| 281 | blockTable[i].cPtr = cPtr; |
| 282 | blockTable[i].resPtr = resPtr; |
| 283 | blockTable[i].srcSize = thisBlockSize; |
| 284 | blockTable[i].cRoom = ZSTD_compressBound(thisBlockSize); |
| 285 | srcPtr += thisBlockSize; |
| 286 | cPtr += blockTable[i].cRoom; |
| 287 | resPtr += thisBlockSize; |
| 288 | remaining -= thisBlockSize; |
| 289 | } |
| 290 | } |
| 291 | |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 292 | /* warmimg up memory */ |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 293 | BMK_datagen(compressedBuffer, maxCompressedSize, 0.10, 1); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 294 | |
| 295 | /* Bench */ |
| 296 | { |
| 297 | int loopNb; |
| 298 | size_t cSize = 0; |
| 299 | double fastestC = 100000000., fastestD = 100000000.; |
| 300 | double ratio = 0.; |
| 301 | U64 crcCheck = 0; |
| 302 | |
| 303 | DISPLAY("\r%79s\r", ""); |
| 304 | for (loopNb = 1; loopNb <= nbIterations; loopNb++) |
| 305 | { |
| 306 | int nbLoops; |
| 307 | int milliTime; |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 308 | U32 blockNb; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 309 | |
| 310 | /* Compression */ |
| Yann Collet | 44fe991 | 2015-10-29 22:02:40 +0100 | [diff] [blame] | 311 | DISPLAY("%2i-%-17.17s :%10u ->\r", loopNb, fileName, (U32)srcSize); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 312 | memset(compressedBuffer, 0xE5, maxCompressedSize); |
| 313 | |
| 314 | nbLoops = 0; |
| 315 | milliTime = BMK_GetMilliStart(); |
| 316 | while (BMK_GetMilliStart() == milliTime); |
| 317 | milliTime = BMK_GetMilliStart(); |
| 318 | while (BMK_GetMilliSpan(milliTime) < TIMELOOP) |
| 319 | { |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 320 | for (blockNb=0; blockNb<nbBlocks; blockNb++) |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 321 | blockTable[blockNb].cSize = compressor(blockTable[blockNb].cPtr, blockTable[blockNb].cRoom, blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize, cLevel); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 322 | nbLoops++; |
| 323 | } |
| 324 | milliTime = BMK_GetMilliSpan(milliTime); |
| 325 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 326 | cSize = 0; |
| 327 | for (blockNb=0; blockNb<nbBlocks; blockNb++) |
| 328 | cSize += blockTable[blockNb].cSize; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 329 | if ((double)milliTime < fastestC*nbLoops) fastestC = (double)milliTime / nbLoops; |
| Yann Collet | 2acb5d3 | 2015-10-29 16:49:43 +0100 | [diff] [blame] | 330 | ratio = (double)srcSize / (double)cSize; |
| Yann Collet | 44fe991 | 2015-10-29 22:02:40 +0100 | [diff] [blame] | 331 | DISPLAY("%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s\r", loopNb, fileName, (int)srcSize, (int)cSize, ratio, (double)srcSize / fastestC / 1000.); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 332 | |
| Yann Collet | 2acb5d3 | 2015-10-29 16:49:43 +0100 | [diff] [blame] | 333 | #if 1 |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 334 | /* Decompression */ |
| 335 | memset(resultBuffer, 0xD6, srcSize); |
| 336 | |
| 337 | nbLoops = 0; |
| 338 | milliTime = BMK_GetMilliStart(); |
| 339 | while (BMK_GetMilliStart() == milliTime); |
| 340 | milliTime = BMK_GetMilliStart(); |
| Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 341 | for ( ; BMK_GetMilliSpan(milliTime) < TIMELOOP; nbLoops++) |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 342 | { |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 343 | for (blockNb=0; blockNb<nbBlocks; blockNb++) |
| 344 | blockTable[blockNb].resSize = ZSTD_decompress(blockTable[blockNb].resPtr, blockTable[blockNb].srcSize, |
| 345 | blockTable[blockNb].cPtr, blockTable[blockNb].cSize); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 346 | } |
| 347 | milliTime = BMK_GetMilliSpan(milliTime); |
| 348 | |
| 349 | if ((double)milliTime < fastestD*nbLoops) fastestD = (double)milliTime / nbLoops; |
| Yann Collet | 44fe991 | 2015-10-29 22:02:40 +0100 | [diff] [blame] | 350 | DISPLAY("%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s ,%6.1f MB/s\r", loopNb, fileName, (int)srcSize, (int)cSize, ratio, (double)srcSize / fastestC / 1000., (double)srcSize / fastestD / 1000.); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 351 | |
| 352 | /* CRC Checking */ |
| 353 | crcCheck = XXH64(resultBuffer, srcSize, 0); |
| 354 | if (crcOrig!=crcCheck) |
| 355 | { |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 356 | unsigned u; |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 357 | unsigned eBlockSize = (unsigned)(MIN(65536*2, blockSize)); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 358 | DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", fileName, (unsigned)crcOrig, (unsigned)crcCheck); |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 359 | for (u=0; u<srcSize; u++) |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 360 | { |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 361 | if (((BYTE*)srcBuffer)[u] != ((BYTE*)resultBuffer)[u]) |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 362 | { |
| Yann Collet | f3eca25 | 2015-10-22 15:31:46 +0100 | [diff] [blame] | 363 | printf("Decoding error at pos %u (block %u, pos %u) \n", u, u / eBlockSize, u % eBlockSize); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 364 | break; |
| 365 | } |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 366 | } |
| 367 | break; |
| 368 | } |
| Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 369 | #endif |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | if (crcOrig == crcCheck) |
| Yann Collet | 44fe991 | 2015-10-29 22:02:40 +0100 | [diff] [blame] | 373 | DISPLAY("%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s ,%6.1f MB/s \n", cLevel, fileName, (int)srcSize, (int)cSize, ratio, (double)srcSize / fastestC / 1000., (double)srcSize / fastestD / 1000.); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | /* End cleaning */ |
| 377 | free(compressedBuffer); |
| 378 | free(resultBuffer); |
| 379 | return 0; |
| 380 | } |
| 381 | |
| 382 | |
| 383 | static U64 BMK_GetFileSize(char* infilename) |
| 384 | { |
| 385 | int r; |
| 386 | #if defined(_MSC_VER) |
| 387 | struct _stat64 statbuf; |
| 388 | r = _stat64(infilename, &statbuf); |
| 389 | #else |
| 390 | struct stat statbuf; |
| 391 | r = stat(infilename, &statbuf); |
| 392 | #endif |
| 393 | if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */ |
| 394 | return (U64)statbuf.st_size; |
| 395 | } |
| 396 | |
| 397 | static size_t BMK_findMaxMem(U64 requiredMem) |
| 398 | { |
| 399 | size_t step = 64 MB; |
| 400 | BYTE* testmem = NULL; |
| 401 | |
| 402 | requiredMem = (((requiredMem >> 26) + 1) << 26); |
| 403 | requiredMem += 2 * step; |
| Yann Collet | 050efba | 2015-11-03 09:49:30 +0100 | [diff] [blame^] | 404 | if (requiredMem > maxMemory) requiredMem = maxMemory; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 405 | |
| 406 | while (!testmem) |
| 407 | { |
| 408 | requiredMem -= step; |
| 409 | testmem = (BYTE*)malloc((size_t)requiredMem); |
| 410 | } |
| 411 | |
| 412 | free(testmem); |
| 413 | return (size_t)(requiredMem - step); |
| 414 | } |
| 415 | |
| 416 | static int BMK_benchOneFile(char* inFileName, int cLevel) |
| 417 | { |
| 418 | FILE* inFile; |
| 419 | U64 inFileSize; |
| 420 | size_t benchedSize, readSize; |
| 421 | void* srcBuffer; |
| Yann Collet | 4114f95 | 2015-10-30 06:40:22 +0100 | [diff] [blame] | 422 | int result=0; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 423 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 424 | /* Check file existence */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 425 | inFile = fopen(inFileName, "rb"); |
| 426 | if (inFile == NULL) |
| 427 | { |
| 428 | DISPLAY("Pb opening %s\n", inFileName); |
| 429 | return 11; |
| 430 | } |
| 431 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 432 | /* Memory allocation & restrictions */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 433 | inFileSize = BMK_GetFileSize(inFileName); |
| 434 | benchedSize = BMK_findMaxMem(inFileSize * 3) / 3; |
| 435 | if ((U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize; |
| 436 | if (benchedSize < inFileSize) |
| 437 | DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", inFileName, (int)(benchedSize >> 20)); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 438 | srcBuffer = malloc(benchedSize); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 439 | if (!srcBuffer) |
| 440 | { |
| 441 | DISPLAY("\nError: not enough memory!\n"); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 442 | fclose(inFile); |
| 443 | return 12; |
| 444 | } |
| 445 | |
| Yann Collet | 1c00dc3 | 2015-10-21 08:22:25 +0100 | [diff] [blame] | 446 | /* Fill input buffer */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 447 | DISPLAY("Loading %s... \r", inFileName); |
| 448 | readSize = fread(srcBuffer, 1, benchedSize, inFile); |
| 449 | fclose(inFile); |
| 450 | |
| 451 | if (readSize != benchedSize) |
| 452 | { |
| 453 | DISPLAY("\nError: problem reading file '%s' !! \n", inFileName); |
| 454 | free(srcBuffer); |
| 455 | return 13; |
| 456 | } |
| 457 | |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 458 | /* Bench */ |
| Yann Collet | c776c46 | 2015-10-29 19:10:54 +0100 | [diff] [blame] | 459 | if (cLevel<0) |
| 460 | { |
| 461 | int l; |
| 462 | for (l=1; l <= -cLevel; l++) |
| 463 | result = BMK_benchMem(srcBuffer, benchedSize, inFileName, l); |
| 464 | } |
| 465 | else |
| 466 | result = BMK_benchMem(srcBuffer, benchedSize, inFileName, cLevel); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 467 | |
| Yann Collet | eeb8ba1 | 2015-10-22 16:55:40 +0100 | [diff] [blame] | 468 | /* clean up */ |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 469 | free(srcBuffer); |
| 470 | DISPLAY("\n"); |
| 471 | return result; |
| 472 | } |
| 473 | |
| 474 | |
| 475 | static int BMK_syntheticTest(int cLevel, double compressibility) |
| 476 | { |
| 477 | size_t benchedSize = 10000000; |
| 478 | void* srcBuffer = malloc(benchedSize); |
| Yann Collet | 4114f95 | 2015-10-30 06:40:22 +0100 | [diff] [blame] | 479 | int result=0; |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 480 | char name[20] = {0}; |
| 481 | |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 482 | /* Memory allocation */ |
| 483 | if (!srcBuffer) |
| 484 | { |
| 485 | DISPLAY("\nError: not enough memory!\n"); |
| 486 | free(srcBuffer); |
| 487 | return 12; |
| 488 | } |
| 489 | |
| 490 | /* Fill input buffer */ |
| 491 | BMK_datagen(srcBuffer, benchedSize, compressibility, 0); |
| 492 | |
| 493 | /* Bench */ |
| 494 | #ifdef _MSC_VER |
| 495 | sprintf_s(name, 20, "Synthetic %2u%%", (unsigned)(compressibility*100)); |
| 496 | #else |
| 497 | snprintf (name, 20, "Synthetic %2u%%", (unsigned)(compressibility*100)); |
| 498 | #endif |
| Yann Collet | c776c46 | 2015-10-29 19:10:54 +0100 | [diff] [blame] | 499 | /* Bench */ |
| 500 | if (cLevel<0) |
| 501 | { |
| 502 | int l; |
| 503 | for (l=1; l <= -cLevel; l++) |
| 504 | result = BMK_benchMem(srcBuffer, benchedSize, name, l); |
| 505 | } |
| 506 | else |
| 507 | result = BMK_benchMem(srcBuffer, benchedSize, name, cLevel); |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 508 | |
| 509 | /* End */ |
| 510 | free(srcBuffer); |
| 511 | DISPLAY("\n"); |
| 512 | return result; |
| 513 | } |
| 514 | |
| 515 | |
| Yann Collet | 213089c | 2015-06-18 07:43:16 -0800 | [diff] [blame] | 516 | int BMK_benchFiles(char** fileNamesTable, unsigned nbFiles, unsigned cLevel) |
| Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 517 | { |
| 518 | double compressibility = (double)g_compressibilityDefault / 100; |
| 519 | |
| 520 | if (nbFiles == 0) |
| 521 | { |
| 522 | BMK_syntheticTest(cLevel, compressibility); |
| 523 | } |
| 524 | else |
| 525 | { |
| 526 | /* Loop for each file */ |
| 527 | unsigned fileIdx = 0; |
| 528 | while (fileIdx<nbFiles) |
| 529 | { |
| 530 | BMK_benchOneFile(fileNamesTable[fileIdx], cLevel); |
| 531 | fileIdx++; |
| 532 | } |
| 533 | } |
| 534 | return 0; |
| 535 | } |
| 536 | |