1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos 12*3117ece4Schristos /*=== Tuning parameter ===*/ 13*3117ece4Schristos #ifndef MAX_TESTED_LEVEL 14*3117ece4Schristos #define MAX_TESTED_LEVEL 12 15*3117ece4Schristos #endif 16*3117ece4Schristos 17*3117ece4Schristos 18*3117ece4Schristos /*=== Dependencies ===*/ 19*3117ece4Schristos #include <stdio.h> // printf 20*3117ece4Schristos #define ZSTD_STATIC_LINKING_ONLY 21*3117ece4Schristos #include <zstd.h> // presumes zstd library is installed 22*3117ece4Schristos #include "common.h" // Helper functions, CHECK(), and CHECK_ZSTD() 23*3117ece4Schristos 24*3117ece4Schristos 25*3117ece4Schristos /*=== functions ===*/ 26*3117ece4Schristos 27*3117ece4Schristos /*! readU32FromChar() : 28*3117ece4Schristos @return : unsigned integer value read from input in `char` format 29*3117ece4Schristos allows and interprets K, KB, KiB, M, MB and MiB suffix. 30*3117ece4Schristos Will also modify `*stringPtr`, advancing it to position where it stopped reading. 31*3117ece4Schristos Note : function result can overflow if digit string > MAX_UINT */ 32*3117ece4Schristos static unsigned readU32FromChar(const char** stringPtr) 33*3117ece4Schristos { 34*3117ece4Schristos unsigned result = 0; 35*3117ece4Schristos while ((**stringPtr >='0') && (**stringPtr <='9')) 36*3117ece4Schristos result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; 37*3117ece4Schristos if ((**stringPtr=='K') || (**stringPtr=='M')) { 38*3117ece4Schristos result <<= 10; 39*3117ece4Schristos if (**stringPtr=='M') result <<= 10; 40*3117ece4Schristos (*stringPtr)++ ; 41*3117ece4Schristos if (**stringPtr=='i') (*stringPtr)++; 42*3117ece4Schristos if (**stringPtr=='B') (*stringPtr)++; 43*3117ece4Schristos } 44*3117ece4Schristos return result; 45*3117ece4Schristos } 46*3117ece4Schristos 47*3117ece4Schristos 48*3117ece4Schristos int main(int argc, char const *argv[]) { 49*3117ece4Schristos 50*3117ece4Schristos printf("\n Zstandard (v%s) memory usage for streaming : \n\n", ZSTD_versionString()); 51*3117ece4Schristos 52*3117ece4Schristos unsigned wLog = 0; 53*3117ece4Schristos if (argc > 1) { 54*3117ece4Schristos const char* valStr = argv[1]; 55*3117ece4Schristos wLog = readU32FromChar(&valStr); 56*3117ece4Schristos } 57*3117ece4Schristos 58*3117ece4Schristos int compressionLevel; 59*3117ece4Schristos for (compressionLevel = 1; compressionLevel <= MAX_TESTED_LEVEL; compressionLevel++) { 60*3117ece4Schristos #define INPUT_SIZE 5 61*3117ece4Schristos #define COMPRESSED_SIZE 128 62*3117ece4Schristos char const dataToCompress[INPUT_SIZE] = "abcde"; 63*3117ece4Schristos char compressedData[COMPRESSED_SIZE]; 64*3117ece4Schristos char decompressedData[INPUT_SIZE]; 65*3117ece4Schristos /* the ZSTD_CCtx_params structure is a way to save parameters and use 66*3117ece4Schristos * them across multiple contexts. We use them here so we can call the 67*3117ece4Schristos * function ZSTD_estimateCStreamSize_usingCCtxParams(). 68*3117ece4Schristos */ 69*3117ece4Schristos ZSTD_CCtx_params* const cctxParams = ZSTD_createCCtxParams(); 70*3117ece4Schristos CHECK(cctxParams != NULL, "ZSTD_createCCtxParams() failed!"); 71*3117ece4Schristos 72*3117ece4Schristos /* Set the compression level. */ 73*3117ece4Schristos CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_compressionLevel, compressionLevel) ); 74*3117ece4Schristos /* Set the window log. 75*3117ece4Schristos * The value 0 means use the default window log, which is equivalent to 76*3117ece4Schristos * not setting it. 77*3117ece4Schristos */ 78*3117ece4Schristos CHECK_ZSTD( ZSTD_CCtxParams_setParameter(cctxParams, ZSTD_c_windowLog, wLog) ); 79*3117ece4Schristos 80*3117ece4Schristos /* Force the compressor to allocate the maximum memory size for a given 81*3117ece4Schristos * level by not providing the pledged source size, or calling 82*3117ece4Schristos * ZSTD_compressStream2() with ZSTD_e_end. 83*3117ece4Schristos */ 84*3117ece4Schristos ZSTD_CCtx* const cctx = ZSTD_createCCtx(); 85*3117ece4Schristos CHECK(cctx != NULL, "ZSTD_createCCtx() failed!"); 86*3117ece4Schristos CHECK_ZSTD( ZSTD_CCtx_setParametersUsingCCtxParams(cctx, cctxParams) ); 87*3117ece4Schristos size_t compressedSize; 88*3117ece4Schristos { 89*3117ece4Schristos ZSTD_inBuffer inBuff = { dataToCompress, sizeof(dataToCompress), 0 }; 90*3117ece4Schristos ZSTD_outBuffer outBuff = { compressedData, sizeof(compressedData), 0 }; 91*3117ece4Schristos CHECK_ZSTD( ZSTD_compressStream(cctx, &outBuff, &inBuff) ); 92*3117ece4Schristos size_t const remaining = ZSTD_endStream(cctx, &outBuff); 93*3117ece4Schristos CHECK_ZSTD(remaining); 94*3117ece4Schristos CHECK(remaining == 0, "Frame not flushed!"); 95*3117ece4Schristos compressedSize = outBuff.pos; 96*3117ece4Schristos } 97*3117ece4Schristos 98*3117ece4Schristos ZSTD_DCtx* const dctx = ZSTD_createDCtx(); 99*3117ece4Schristos CHECK(dctx != NULL, "ZSTD_createDCtx() failed!"); 100*3117ece4Schristos /* Set the maximum allowed window log. 101*3117ece4Schristos * The value 0 means use the default window log, which is equivalent to 102*3117ece4Schristos * not setting it. 103*3117ece4Schristos */ 104*3117ece4Schristos CHECK_ZSTD( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, wLog) ); 105*3117ece4Schristos /* forces decompressor to use maximum memory size, since the 106*3117ece4Schristos * decompressed size is not stored in the frame header. 107*3117ece4Schristos */ 108*3117ece4Schristos { ZSTD_inBuffer inBuff = { compressedData, compressedSize, 0 }; 109*3117ece4Schristos ZSTD_outBuffer outBuff = { decompressedData, sizeof(decompressedData), 0 }; 110*3117ece4Schristos size_t const remaining = ZSTD_decompressStream(dctx, &outBuff, &inBuff); 111*3117ece4Schristos CHECK_ZSTD(remaining); 112*3117ece4Schristos CHECK(remaining == 0, "Frame not complete!"); 113*3117ece4Schristos CHECK(outBuff.pos == sizeof(dataToCompress), "Bad decompression!"); 114*3117ece4Schristos } 115*3117ece4Schristos 116*3117ece4Schristos size_t const cstreamSize = ZSTD_sizeof_CStream(cctx); 117*3117ece4Schristos size_t const cstreamEstimatedSize = ZSTD_estimateCStreamSize_usingCCtxParams(cctxParams); 118*3117ece4Schristos size_t const dstreamSize = ZSTD_sizeof_DStream(dctx); 119*3117ece4Schristos size_t const dstreamEstimatedSize = ZSTD_estimateDStreamSize_fromFrame(compressedData, compressedSize); 120*3117ece4Schristos 121*3117ece4Schristos CHECK(cstreamSize <= cstreamEstimatedSize, "Compression mem (%u) > estimated (%u)", 122*3117ece4Schristos (unsigned)cstreamSize, (unsigned)cstreamEstimatedSize); 123*3117ece4Schristos CHECK(dstreamSize <= dstreamEstimatedSize, "Decompression mem (%u) > estimated (%u)", 124*3117ece4Schristos (unsigned)dstreamSize, (unsigned)dstreamEstimatedSize); 125*3117ece4Schristos 126*3117ece4Schristos printf("Level %2i : Compression Mem = %5u KB (estimated : %5u KB) ; Decompression Mem = %4u KB (estimated : %5u KB)\n", 127*3117ece4Schristos compressionLevel, 128*3117ece4Schristos (unsigned)(cstreamSize>>10), (unsigned)(cstreamEstimatedSize>>10), 129*3117ece4Schristos (unsigned)(dstreamSize>>10), (unsigned)(dstreamEstimatedSize>>10)); 130*3117ece4Schristos 131*3117ece4Schristos ZSTD_freeDCtx(dctx); 132*3117ece4Schristos ZSTD_freeCCtx(cctx); 133*3117ece4Schristos ZSTD_freeCCtxParams(cctxParams); 134*3117ece4Schristos if (wLog) break; /* single test */ 135*3117ece4Schristos } 136*3117ece4Schristos return 0; 137*3117ece4Schristos } 138