benchmark silo added
[c11concurrency-benchmarks.git] / silo / third-party / lz4 / bench.c
diff --git a/silo/third-party/lz4/bench.c b/silo/third-party/lz4/bench.c
new file mode 100644 (file)
index 0000000..f605249
--- /dev/null
@@ -0,0 +1,434 @@
+/*\r
+    bench.c - Demo program to benchmark open-source compression algorithm\r
+    Copyright (C) Yann Collet 2012-2013\r
+    GPL v2 License\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License along\r
+    with this program; if not, write to the Free Software Foundation, Inc.,\r
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+\r
+    You can contact the author at :\r
+    - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\r
+    - LZ4 source repository : http://code.google.com/p/lz4/\r
+*/\r
+\r
+//**************************************\r
+// Compiler Options\r
+//**************************************\r
+// Disable some Visual warning messages\r
+#define _CRT_SECURE_NO_WARNINGS\r
+#define _CRT_SECURE_NO_DEPRECATE     // VS2005\r
+\r
+// Unix Large Files support (>4GB)\r
+#if (defined(__sun__) && (!defined(__LP64__)))   // Sun Solaris 32-bits requires specific definitions\r
+#  define _LARGEFILE_SOURCE \r
+#  define _FILE_OFFSET_BITS 64\r
+#elif ! defined(__LP64__)                        // No point defining Large file for 64 bit\r
+#  define _LARGEFILE64_SOURCE\r
+#endif\r
+\r
+// S_ISREG & gettimeofday() are not supported by MSVC\r
+#if defined(_MSC_VER)\r
+#  define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)\r
+#  define BMK_LEGACY_TIMER 1\r
+#endif\r
+\r
+// GCC does not support _rotl outside of Windows\r
+#if !defined(_WIN32)\r
+#  define _rotl(x,r) ((x << r) | (x >> (32 - r)))\r
+#endif\r
+\r
+\r
+//**************************************\r
+// Includes\r
+//**************************************\r
+#include <stdlib.h>      // malloc\r
+#include <stdio.h>       // fprintf, fopen, ftello64\r
+#include <sys/types.h>   // stat64\r
+#include <sys/stat.h>    // stat64\r
+\r
+// Use ftime() if gettimeofday() is not available on your target\r
+#if defined(BMK_LEGACY_TIMER)\r
+#  include <sys/timeb.h>   // timeb, ftime\r
+#else\r
+#  include <sys/time.h>    // gettimeofday\r
+#endif\r
+\r
+#include "lz4.h"\r
+#define COMPRESSOR0 LZ4_compress\r
+#include "lz4hc.h"\r
+#define COMPRESSOR1 LZ4_compressHC\r
+#define DEFAULTCOMPRESSOR COMPRESSOR0\r
+\r
+#include "xxhash.h"\r
+\r
+\r
+//**************************************\r
+// Basic Types\r
+//**************************************\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99\r
+# include <stdint.h>\r
+  typedef uint8_t  BYTE;\r
+  typedef uint16_t U16;\r
+  typedef uint32_t U32;\r
+  typedef  int32_t S32;\r
+  typedef uint64_t U64;\r
+#else\r
+  typedef unsigned char       BYTE;\r
+  typedef unsigned short      U16;\r
+  typedef unsigned int        U32;\r
+  typedef   signed int        S32;\r
+  typedef unsigned long long  U64;\r
+#endif\r
+\r
+\r
+//**************************************\r
+// Constants\r
+//**************************************\r
+#define NBLOOPS    3\r
+#define TIMELOOP   2000\r
+\r
+#define KNUTH      2654435761U\r
+#define MAX_MEM    (1984<<20)\r
+#define DEFAULT_CHUNKSIZE   (4<<20)\r
+\r
+\r
+//**************************************\r
+// Local structures\r
+//**************************************\r
+struct chunkParameters\r
+{\r
+    U32   id;\r
+    char* origBuffer;\r
+    char* compressedBuffer;\r
+    int   origSize;\r
+    int   compressedSize;\r
+};\r
+\r
+struct compressionParameters\r
+{\r
+    int (*compressionFunction)(const char*, char*, int);\r
+    int (*decompressionFunction)(const char*, char*, int);\r
+};\r
+\r
+\r
+//**************************************\r
+// MACRO\r
+//**************************************\r
+#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\r
+\r
+\r
+\r
+//**************************************\r
+// Benchmark Parameters\r
+//**************************************\r
+static int chunkSize = DEFAULT_CHUNKSIZE;\r
+static int nbIterations = NBLOOPS;\r
+static int BMK_pause = 0;\r
+\r
+void BMK_SetBlocksize(int bsize)\r
+{\r
+    chunkSize = bsize;\r
+    DISPLAY("-Using Block Size of %i KB-\n", chunkSize>>10);\r
+}\r
+\r
+void BMK_SetNbIterations(int nbLoops)\r
+{\r
+    nbIterations = nbLoops;\r
+    DISPLAY("- %i iterations -\n", nbIterations);\r
+}\r
+\r
+void BMK_SetPause()\r
+{\r
+    BMK_pause = 1;\r
+}\r
+\r
+//*********************************************************\r
+//  Private functions\r
+//*********************************************************\r
+\r
+#if defined(BMK_LEGACY_TIMER)\r
+\r
+static int BMK_GetMilliStart()\r
+{\r
+  // Based on Legacy ftime()\r
+  // Rolls over every ~ 12.1 days (0x100000/24/60/60)\r
+  // Use GetMilliSpan to correct for rollover\r
+  struct timeb tb;\r
+  int nCount;\r
+  ftime( &tb );\r
+  nCount = (int) (tb.millitm + (tb.time & 0xfffff) * 1000);\r
+  return nCount;\r
+}\r
+\r
+#else\r
+\r
+static int BMK_GetMilliStart()\r
+{\r
+  // Based on newer gettimeofday()\r
+  // Use GetMilliSpan to correct for rollover\r
+  struct timeval tv;\r
+  int nCount;\r
+  gettimeofday(&tv, NULL);\r
+  nCount = (int) (tv.tv_usec/1000 + (tv.tv_sec & 0xfffff) * 1000);\r
+  return nCount;\r
+}\r
+\r
+#endif\r
+\r
+\r
+static int BMK_GetMilliSpan( int nTimeStart )\r
+{\r
+  int nSpan = BMK_GetMilliStart() - nTimeStart;\r
+  if ( nSpan < 0 )\r
+    nSpan += 0x100000 * 1000;\r
+  return nSpan;\r
+}\r
+\r
+\r
+static size_t BMK_findMaxMem(U64 requiredMem)\r
+{\r
+    size_t step = (64U<<20);   // 64 MB\r
+    BYTE* testmem=NULL;\r
+\r
+    requiredMem = (((requiredMem >> 25) + 1) << 26);\r
+    if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;\r
+\r
+    requiredMem += 2*step;\r
+    while (!testmem)\r
+    {\r
+        requiredMem -= step;\r
+        testmem = (BYTE*) malloc ((size_t)requiredMem);\r
+    }\r
+\r
+    free (testmem);\r
+    return (size_t) (requiredMem - step);\r
+}\r
+\r
+\r
+static U64 BMK_GetFileSize(char* infilename)\r
+{\r
+    int r;\r
+#if defined(_MSC_VER)\r
+    struct _stat64 statbuf;\r
+    r = _stat64(infilename, &statbuf);\r
+#else\r
+    struct stat statbuf;\r
+    r = stat(infilename, &statbuf);\r
+#endif\r
+    if (r || !S_ISREG(statbuf.st_mode)) return 0;   // No good...\r
+    return (U64)statbuf.st_size;\r
+}\r
+\r
+\r
+//*********************************************************\r
+//  Public function\r
+//*********************************************************\r
+\r
+int BMK_benchFile(char** fileNamesTable, int nbFiles, int cLevel)\r
+{\r
+  int fileIdx=0;\r
+  FILE* fileIn;\r
+  char* infilename;\r
+  U64 largefilesize;\r
+  size_t benchedSize;\r
+  int nbChunks;\r
+  int maxCChunkSize;\r
+  size_t readSize;\r
+  char* orig_buff;\r
+  char* compressed_buff; int compressed_buff_size;\r
+  struct chunkParameters* chunkP;\r
+  U32 crcc, crcd=0;\r
+  struct compressionParameters compP;\r
+\r
+  U64 totals = 0;\r
+  U64 totalz = 0;\r
+  double totalc = 0.;\r
+  double totald = 0.;\r
+\r
+\r
+  // Init\r
+  switch (cLevel)\r
+  {\r
+#ifdef COMPRESSOR0\r
+  case 0 : compP.compressionFunction = COMPRESSOR0; break;\r
+#endif\r
+#ifdef COMPRESSOR1\r
+  case 1 : compP.compressionFunction = COMPRESSOR1; break;\r
+#endif\r
+  default : compP.compressionFunction = DEFAULTCOMPRESSOR;\r
+  }\r
+  compP.decompressionFunction = LZ4_decompress_fast;\r
+\r
+  // Loop for each file\r
+  while (fileIdx<nbFiles)\r
+  {\r
+      // Check file existence\r
+      infilename = fileNamesTable[fileIdx++];\r
+      fileIn = fopen( infilename, "rb" );\r
+      if (fileIn==NULL)\r
+      {\r
+        DISPLAY( "Pb opening %s\n", infilename);\r
+        return 11;\r
+      }\r
+\r
+      // Memory allocation & restrictions\r
+      largefilesize = BMK_GetFileSize(infilename);\r
+      benchedSize = (size_t) BMK_findMaxMem(largefilesize) / 2;\r
+      if ((U64)benchedSize > largefilesize) benchedSize = (size_t)largefilesize;\r
+      if (benchedSize < largefilesize)\r
+      {\r
+          DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", infilename, (int)(benchedSize>>20));\r
+      }\r
+\r
+      // Alloc\r
+      chunkP = (struct chunkParameters*) malloc(((benchedSize / chunkSize)+1) * sizeof(struct chunkParameters));\r
+      orig_buff = (char*)malloc((size_t )benchedSize);\r
+      nbChunks = (int) (benchedSize / chunkSize) + 1;\r
+      maxCChunkSize = LZ4_compressBound(chunkSize);\r
+      compressed_buff_size = nbChunks * maxCChunkSize;\r
+      compressed_buff = (char*)malloc((size_t )compressed_buff_size);\r
+\r
+\r
+      if(!orig_buff || !compressed_buff)\r
+      {\r
+        DISPLAY("\nError: not enough memory!\n");\r
+        free(orig_buff);\r
+        free(compressed_buff);\r
+        fclose(fileIn);\r
+        return 12;\r
+      }\r
+\r
+      // Init chunks data\r
+      {\r
+          int i;\r
+          size_t remaining = benchedSize;\r
+          char* in = orig_buff;\r
+          char* out = compressed_buff;\r
+          for (i=0; i<nbChunks; i++)\r
+          {\r
+              chunkP[i].id = i;\r
+              chunkP[i].origBuffer = in; in += chunkSize;\r
+              if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }\r
+              chunkP[i].compressedBuffer = out; out += maxCChunkSize;\r
+              chunkP[i].compressedSize = 0;\r
+          }\r
+      }\r
+\r
+      // Fill input buffer\r
+      DISPLAY("Loading %s...       \r", infilename);\r
+      readSize = fread(orig_buff, 1, benchedSize, fileIn);\r
+      fclose(fileIn);\r
+\r
+      if(readSize != benchedSize)\r
+      {\r
+        DISPLAY("\nError: problem reading file '%s' !!    \n", infilename);\r
+        free(orig_buff);\r
+        free(compressed_buff);\r
+        return 13;\r
+      }\r
+\r
+      // Calculating input Checksum\r
+      crcc = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
+\r
+\r
+      // Bench\r
+      {\r
+        int loopNb, nb_loops, chunkNb;\r
+        size_t cSize=0;\r
+        int milliTime;\r
+        double fastestC = 100000000., fastestD = 100000000.;\r
+        double ratio=0.;\r
+\r
+        DISPLAY("\r%79s\r", "");\r
+        for (loopNb = 1; loopNb <= nbIterations; loopNb++)\r
+        {\r
+          // Compression\r
+          DISPLAY("%1i-%-14.14s : %9i ->\r", loopNb, infilename, (int)benchedSize);\r
+          { size_t i; for (i=0; i<benchedSize; i++) compressed_buff[i]=(char)i; }     // warmimg up memory\r
+\r
+          nb_loops = 0;\r
+          milliTime = BMK_GetMilliStart();\r
+          while(BMK_GetMilliStart() == milliTime);\r
+          milliTime = BMK_GetMilliStart();\r
+          while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
+          {\r
+            for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
+                chunkP[chunkNb].compressedSize = compP.compressionFunction(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);\r
+            nb_loops++;\r
+          }\r
+          milliTime = BMK_GetMilliSpan(milliTime);\r
+\r
+          if ((double)milliTime < fastestC*nb_loops) fastestC = (double)milliTime/nb_loops;\r
+          cSize=0; for (chunkNb=0; chunkNb<nbChunks; chunkNb++) cSize += chunkP[chunkNb].compressedSize;\r
+          ratio = (double)cSize/(double)benchedSize*100.;\r
+\r
+          DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000.);\r
+\r
+          // Decompression\r
+          { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; }     // zeroing area, for CRC checking\r
+\r
+          nb_loops = 0;\r
+          milliTime = BMK_GetMilliStart();\r
+          while(BMK_GetMilliStart() == milliTime);\r
+          milliTime = BMK_GetMilliStart();\r
+          while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
+          {\r
+            for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
+                //chunkP[chunkNb].origSize = LZ4_decompress_safe(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+                chunkP[chunkNb].compressedSize = LZ4_decompress_fast(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+                //chunkP[chunkNb].compressedSize = LZ4_decompress_fast_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+                //chunkP[chunkNb].origSize = LZ4_decompress_safe_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+                //chunkP[chunkNb].origSize = LZ4_decompress_safe_partial(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize-5, chunkSize);\r
+                //chunkP[chunkNb].compressedSize = LZ4_uncompress(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+                //chunkP[chunkNb].origSize = LZ4_uncompress_unknownOutputSize(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+            nb_loops++;\r
+          }\r
+          milliTime = BMK_GetMilliSpan(milliTime);\r
+\r
+          if ((double)milliTime < fastestD*nb_loops) fastestD = (double)milliTime/nb_loops;\r
+          DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+\r
+          // CRC Checking\r
+          crcd = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
+          if (crcc!=crcd) { DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", infilename, (unsigned)crcc, (unsigned)crcd); break; }\r
+        }\r
+\r
+        if (crcc==crcd)\r
+        {\r
+            if (ratio<100.)\r
+                DISPLAY("%-16.16s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+            else\r
+                DISPLAY("%-16.16s : %9i -> %9i (%5.1f%%),%7.1f MB/s ,%7.1f MB/s \n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+        }\r
+        totals += benchedSize;\r
+        totalz += cSize;\r
+        totalc += fastestC;\r
+        totald += fastestD;\r
+      }\r
+\r
+      free(orig_buff);\r
+      free(compressed_buff);\r
+      free(chunkP);\r
+  }\r
+\r
+  if (nbFiles > 1)\r
+        DISPLAY("%-16.16s :%10llu ->%10llu (%5.2f%%), %6.1f MB/s , %6.1f MB/s\n", "  TOTAL", (long long unsigned int)totals, (long long unsigned int)totalz, (double)totalz/(double)totals*100., (double)totals/totalc/1000., (double)totals/totald/1000.);\r
+\r
+  if (BMK_pause) { DISPLAY("press enter...\n"); getchar(); }\r
+\r
+  return 0;\r
+}\r
+\r
+\r
+\r