LCOV - code coverage report
Current view: top level - benchmarks - opmphm.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 1104 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 33 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief The Order Preserving Minimal Perfect Hash Map C benchmark.
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : // ==== DEFINE SECTION ====
      10             : #define _GNU_SOURCE
      11             : #define KDBRAND_BENCHMARK // allows the seed injection into Elektra
      12             : // uncomment to use OPENMP and set USE_OPENMP in CMakeLists.txt
      13             : //~ #define USE_OPENMP
      14             : 
      15             : #ifdef USE_OPENMP
      16             : // set here you number of threads
      17             : #define NUMBEROFTHREADS 8
      18             : #else
      19             : #define NUMBEROFTHREADS 1
      20             : #endif
      21             : 
      22             : // ==== INCLUDE SECTION ====
      23             : #include "benchmarks.h"
      24             : #ifdef HAVE_HSEARCHR
      25             : #include <search.h>
      26             : #endif
      27             : 
      28             : #ifdef USE_OPENMP
      29             : #include <omp.h>
      30             : #endif
      31             : 
      32             : #include "../src/libs/elektra/opmphm.c"
      33             : #include "../src/libs/elektra/opmphmpredictor.c"
      34             : #include "../src/libs/elektra/rand.c"
      35             : #include <sys/time.h>
      36             : 
      37             : int32_t elektraRandBenchmarkInitSeed;
      38             : 
      39             : // benchmarks helpers
      40             : static int32_t * getRandomSeed (int32_t * seed);
      41             : static FILE * openOutFileWithRPartitePostfix (const char * name, uint8_t r);
      42             : static const char * getString (void * data);
      43             : static size_t getPower (size_t p, size_t q);
      44             : static int cmpInteger (const void * a, const void * b);
      45             : // generate KeySets
      46             : static KeySetShape * getKeySetShapes (void);
      47             : const size_t numberOfShapes = 8;
      48             : 
      49             : 
      50             : /**
      51             :  * General structure of a benchmark
      52             :  *
      53             :  * `name` is a unique name of the benchmark and `benchmarkF` is the independent function executing the benchmark.
      54             :  * Execute a benchmark with benchmark_opmphm `name`.
      55             :  */
      56             : typedef struct
      57             : {
      58             :         char * name;
      59             :         size_t numberOfSeedsNeeded;
      60             :         void (*benchmarkF) (char *);
      61             : } Benchmark;
      62             : 
      63             : 
      64             : /**
      65             :  * START ======================================= Measures the Opmphm Hash Function time ============================================== START
      66             :  *
      67             :  * This benchmark measures the time for hashing a whole KeySet, variegating in the size. Executed multiple times.
      68             :  *
      69             :  * The output has the following header: n;n;n;n;... (for each KeySetShape)
      70             :  *
      71             :  * This benchmark takes numberOfShapes * nCount seeds
      72             :  */
      73           0 : static void benchmarkHashFunctionTime (char * name)
      74             : {
      75           0 :         const size_t nCount = 4;
      76           0 :         const size_t n[] = { 10, 100, 1000, 10000 };
      77           0 :         const size_t runs = 11;
      78             :         // init results
      79           0 :         size_t * results = elektraMalloc (nCount * numberOfShapes * runs * sizeof (size_t));
      80           0 :         if (!results)
      81             :         {
      82           0 :                 printExit ("malloc");
      83             :         }
      84             :         // benchmark
      85           0 :         printf ("Run Benchmark %s:\n", name);
      86           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
      87           0 :         for (size_t i = 0; i < nCount; ++i)
      88             :         {
      89           0 :                 for (size_t s = 0; s < numberOfShapes; ++s)
      90             :                 {
      91           0 :                         printf ("now at n: %zu/%zu shape: %zu/%zu\r", i, nCount, s, numberOfShapes);
      92           0 :                         fflush (stdout);
      93             :                         int32_t seed;
      94           0 :                         if (getRandomSeed (&seed) != &seed) printExit ("Seed Parsing Error or feed me more seeds");
      95           0 :                         KeySet * ks = generateKeySet (n[i], &seed, &keySetShapes[s]);
      96           0 :                         for (size_t r = 0; r < runs; ++r)
      97             :                         {
      98             :                                 Key * key;
      99           0 :                                 ksRewind (ks);
     100             :                                 struct timeval start;
     101             :                                 struct timeval end;
     102           0 :                                 __asm__("");
     103           0 :                                 gettimeofday (&start, 0);
     104           0 :                                 __asm__("");
     105             :                                 // measure
     106           0 :                                 while ((key = ksNext (ks)))
     107             :                                 {
     108           0 :                                         __asm__("");
     109           0 :                                         opmphmHashfunction (keyName (key), strlen (keyName (key)), 1337);
     110           0 :                                         __asm__("");
     111             :                                 }
     112           0 :                                 __asm__("");
     113           0 :                                 gettimeofday (&end, 0);
     114           0 :                                 __asm__("");
     115           0 :                                 results[i * (numberOfShapes * runs) + s * runs + r] =
     116           0 :                                         (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
     117             :                         }
     118           0 :                         ksDel (ks);
     119             :                 }
     120             :         }
     121           0 :         elektraFree (keySetShapes);
     122             :         // wirte out results
     123           0 :         FILE * out = openOutFileWithRPartitePostfix ("benchmark_opmphm_hashfunctiontime", 0);
     124           0 :         if (!out)
     125             :         {
     126           0 :                 printExit ("open out file");
     127             :         }
     128             :         // print header
     129           0 :         for (size_t i = 0; i < nCount; ++i)
     130             :         {
     131           0 :                 for (size_t s = 0; s < numberOfShapes; ++s)
     132             :                 {
     133           0 :                         if (!s && !i)
     134             :                         {
     135           0 :                                 fprintf (out, "%zu", n[i]);
     136             :                         }
     137             :                         else
     138             :                         {
     139           0 :                                 fprintf (out, ";%zu", n[i]);
     140             :                         }
     141             :                 }
     142             :         }
     143           0 :         fprintf (out, "\n");
     144             :         // print data
     145           0 :         for (size_t r = 0; r < runs; ++r)
     146             :         {
     147           0 :                 for (size_t i = 0; i < nCount; ++i)
     148             :                 {
     149           0 :                         for (size_t s = 0; s < numberOfShapes; ++s)
     150             :                         {
     151           0 :                                 if (!s && !i)
     152             :                                 {
     153           0 :                                         fprintf (out, "%zu", results[i * (numberOfShapes * runs) + s * runs + r]);
     154             :                                 }
     155             :                                 else
     156             :                                 {
     157           0 :                                         fprintf (out, ";%zu", results[i * (numberOfShapes * runs) + s * runs + r]);
     158             :                                 }
     159             :                         }
     160             :                 }
     161           0 :                 fprintf (out, "\n");
     162             :         }
     163           0 :         fclose (out);
     164           0 :         elektraFree (results);
     165           0 : }
     166             : /**
     167             :  * END ========================================= Measures the Opmphm Hash Function time ================================================ END
     168             :  */
     169             : 
     170             : /**
     171             :  * START ======================================================= Mapping ============================================================= START
     172             :  *
     173             :  * This benchmark counts the opmphmMapping (...)  invocations until success, for each KeySet size (n) and space influencing parameter (c).
     174             :  * First the KeySets are build, for every KeySet size (n) there are numberOfShapes * keySetsPerShape KeySets.
     175             :  * Then the benchmarking for every KeySet size (n) and space influencing parameter (c) takes place, with a fixed set of seeds for
     176             :  * the opmphmMapping (...) invocations.
     177             :  * At the end the results are written out in the following format:
     178             :  *
     179             :  * trials;n_%zuc_%f;... (each n and c are unique)
     180             :  *
     181             :  * The number of needed seeds for this benchmarks is: nCount * numberOfShapes * keySetsPerShape (KeySets generation) + numberOfSeeds (tested
     182             :  * seeds)
     183             :  */
     184             : 
     185           0 : static void benchmarkMappingCheckOpmphm (Opmphm * opmphm, OpmphmGraph * graph, size_t n, OpmphmInit * init, size_t mappings,
     186             :                                          size_t maxMappings)
     187             : {
     188           0 :         if (n < 5 && mappings != maxMappings)
     189             :         {
     190             :                 // assign
     191           0 :                 if (opmphmAssignment (opmphm, graph, n, 1))
     192             :                 {
     193           0 :                         printExit ("check assignment failed");
     194             :                 }
     195           0 :                 for (size_t i = 0; i < n; ++i)
     196             :                 {
     197           0 :                         if (i != opmphmLookup (opmphm, n, init->getName (init->data[i])))
     198             :                         {
     199           0 :                                 printExit ("check assignment failed");
     200             :                         }
     201             :                 }
     202           0 :                 opmphmClear (opmphm);
     203             :         }
     204           0 : }
     205             : 
     206           0 : static void benchmarkMapping (char * name)
     207             : {
     208           0 :         size_t rUniPar = 3;
     209           0 :         const size_t nCount = 15;
     210           0 :         const size_t n[] = { 10, 15, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480, 640, 960, 1280 }; // 15
     211           0 :         const size_t cCount = 15;
     212           0 :         const double c[] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 }; // 15
     213           0 :         const size_t keySetsPerShape = 20;
     214           0 :         const size_t numberOfKeySets = nCount * numberOfShapes * keySetsPerShape;
     215             : 
     216           0 :         const size_t numberOfSeeds = 10000;
     217           0 :         const size_t maxMappings = 10; // the maximum trials for one opmphmMapping (...) invocation series.
     218             : 
     219             :         // init seed population, used for opmphmMapping (...) invocation.
     220           0 :         int32_t * seeds = elektraMalloc (numberOfSeeds * sizeof (int32_t));
     221           0 :         if (!seeds)
     222             :         {
     223           0 :                 printExit ("malloc");
     224             :         }
     225             :         // get seeds
     226           0 :         for (size_t i = 0; i < numberOfSeeds; ++i)
     227             :         {
     228           0 :                 if (getRandomSeed (&seeds[i]) != &seeds[i]) printExit ("Seed Parsing Error or feed me more seeds");
     229             :         }
     230             : 
     231             :         // init results
     232           0 :         size_t * results = elektraMalloc (nCount * cCount * maxMappings * sizeof (size_t));
     233           0 :         if (!results)
     234             :         {
     235           0 :                 printExit ("malloc");
     236             :         }
     237           0 :         memset (results, 0, nCount * cCount * maxMappings * sizeof (size_t));
     238             : 
     239             :         // Generate all KeySets
     240           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
     241           0 :         KeySet ** keySetsCache = elektraMalloc (numberOfKeySets * sizeof (KeySet *));
     242           0 :         if (!keySetsCache)
     243             :         {
     244           0 :                 printExit ("malloc");
     245             :         }
     246           0 :         printf ("KeySet Cache Build:\n");
     247           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     248             :         {
     249           0 :                 printf ("now at: %zu/%zu\r", nI + 1, nCount);
     250           0 :                 fflush (stdout);
     251           0 :                 for (size_t shapeI = 0; shapeI < numberOfShapes; ++shapeI)
     252             :                 {
     253           0 :                         for (size_t ksPshapeI = 0; ksPshapeI < keySetsPerShape; ++ksPshapeI)
     254             :                         {
     255             :                                 int32_t genSeed;
     256           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
     257           0 :                                 keySetsCache[nI * (numberOfShapes * keySetsPerShape) + shapeI * keySetsPerShape + ksPshapeI] =
     258           0 :                                         generateKeySet (n[nI], &genSeed, &keySetShapes[shapeI]);
     259             :                         }
     260             :                 }
     261             :         }
     262             : 
     263           0 :         printf ("\nRun Benchmark %s:\n", name);
     264             : 
     265             : #ifdef USE_OPENMP
     266             :         omp_set_num_threads (NUMBEROFTHREADS);
     267             :         // lock
     268             :         omp_lock_t writeLock;
     269             :         omp_init_lock (&writeLock);
     270             : #endif
     271             :         // split
     272             :         if (numberOfSeeds % NUMBEROFTHREADS != 0) printExit ("seeds % NUMBEROFTHREADS != 0");
     273           0 :         size_t partSize = numberOfSeeds / NUMBEROFTHREADS;
     274             : 
     275             :         // init threads local results
     276             :         size_t * localResults[NUMBEROFTHREADS];
     277           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     278             :         {
     279           0 :                 localResults[i] = elektraMalloc (nCount * cCount * maxMappings * sizeof (size_t));
     280           0 :                 if (!localResults[i])
     281             :                 {
     282           0 :                         printExit ("malloc");
     283             :                 }
     284             :         }
     285             : 
     286             :         // for all nCount
     287           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     288             :         {
     289             :                 // and cCount
     290           0 :                 for (size_t cI = 0; cI < cCount; ++cI)
     291             :                 {
     292           0 :                         printf ("now at: n = %zu/%zu c = %zu/%zu\r", nI + 1, nCount, cI + 1, cCount);
     293           0 :                         fflush (stdout);
     294             :                         // OPMPHM for all threads
     295             :                         Opmphm * opmphms[NUMBEROFTHREADS];
     296             :                         OpmphmGraph * graphs[NUMBEROFTHREADS];
     297           0 :                         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     298             :                         {
     299           0 :                                 opmphms[i] = opmphmNew ();
     300           0 :                                 if (!opmphms[i]) printExit ("opmphm");
     301           0 :                                 graphs[i] = opmphmGraphNew (opmphms[i], rUniPar, n[nI], opmphmMinC (rUniPar) + c[cI]);
     302           0 :                                 if (!graphs[i]) printExit ("graph");
     303             :                         }
     304             :                         // OPMPHM
     305             : 
     306             :                         // go through all KeySets from n
     307           0 :                         for (size_t ksCacheI = 0; ksCacheI < numberOfShapes * keySetsPerShape; ++ksCacheI)
     308             :                         {
     309           0 :                                 KeySet * ks = keySetsCache[nI * (numberOfShapes * keySetsPerShape) + ksCacheI];
     310             : #ifdef USE_OPENMP
     311             : #pragma omp parallel
     312             : #endif
     313             :                                 {
     314           0 :                                         size_t threadI = 0;
     315             :                                         // OPMPHM
     316             :                                         OpmphmInit init;
     317           0 :                                         init.getName = getString;
     318           0 :                                         init.data = (void **) (ks->array);
     319             : // OPMPHM
     320             : #ifdef USE_OPENMP
     321             :                                         threadI = omp_get_thread_num ();
     322             : #endif
     323             :                                         // reset local result
     324           0 :                                         memset (localResults[threadI], 0, nCount * cCount * maxMappings * sizeof (size_t));
     325             : 
     326             :                                         // try each seed part
     327           0 :                                         for (size_t seedI = threadI * partSize; seedI < (threadI + 1) * partSize; ++seedI)
     328             :                                         {
     329           0 :                                                 size_t mappings = 0; // counts mapping invocations
     330             :                                                 // OPMPHM
     331           0 :                                                 init.initSeed = seeds[seedI];
     332             :                                                 // fresh OpmphmGraph
     333           0 :                                                 opmphmGraphClear (opmphms[threadI], graphs[threadI]);
     334             :                                                 // do benchmark
     335             :                                                 int ret;
     336             :                                                 do
     337             :                                                 {
     338           0 :                                                         ret = opmphmMapping (opmphms[threadI], graphs[threadI], &init, n[nI]);
     339           0 :                                                         ++mappings;
     340           0 :                                                 } while (ret && mappings < maxMappings);
     341             :                                                 // OPMPHM
     342           0 :                                                 if (mappings < 1 || mappings > maxMappings)
     343             :                                                 {
     344           0 :                                                         printExit ("benchmarkSeedRangeMappingCount: mappings out of range");
     345             :                                                 }
     346             :                                                 // check opmphm
     347           0 :                                                 benchmarkMappingCheckOpmphm (opmphms[threadI], graphs[threadI], n[nI], &init, mappings,
     348             :                                                                              maxMappings);
     349             :                                                 // save result
     350             :                                                 // shift, because 0 not used
     351           0 :                                                 --mappings;
     352           0 :                                                 ++localResults[threadI][nI * (cCount * maxMappings) + cI * maxMappings + mappings];
     353             :                                         }
     354             : #ifdef USE_OPENMP
     355             :                                         // write local to global
     356             :                                         omp_set_lock (&writeLock);
     357             : #endif
     358           0 :                                         for (size_t i = 0; i < nCount * cCount * maxMappings; ++i)
     359             :                                         {
     360           0 :                                                 results[i] += localResults[threadI][i];
     361             :                                         }
     362             : #ifdef USE_OPENMP
     363             :                                         omp_unset_lock (&writeLock);
     364             : #endif
     365             :                                 }
     366             :                         }
     367           0 :                         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     368             :                         {
     369             :                                 // OPMPHM
     370           0 :                                 opmphmDel (opmphms[i]);
     371           0 :                                 opmphmGraphDel (graphs[i]);
     372             :                                 // OPMPHM
     373             :                         }
     374             :                 }
     375             :                 // end for all nCount
     376             :         }
     377             : #ifdef USE_OPENMP
     378             :         omp_destroy_lock (&writeLock);
     379             : #endif
     380           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     381             :         {
     382           0 :                 free (localResults[i]);
     383             :         }
     384           0 :         printf ("\n");
     385             : 
     386             :         /*
     387             :          * results sanity check
     388             :          *
     389             :          * each n and c should have in sum (numberOfShapes * keySetsPerShape) for each KeySet times (numberOfSeeds) seeds trials
     390             :          */
     391           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     392             :         {
     393           0 :                 for (size_t cI = 0; cI < cCount; ++cI)
     394             :                 {
     395             :                         size_t sum = 0;
     396           0 :                         for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     397             :                         {
     398           0 :                                 sum += results[nI * (cCount * maxMappings) + cI * maxMappings + mappingI];
     399             :                         }
     400           0 :                         if (sum != numberOfShapes * keySetsPerShape * numberOfSeeds)
     401             :                         {
     402           0 :                                 printExit ("benchmarkSeedRangeMappingCount: results sanity check failed");
     403             :                         }
     404             :                 }
     405             :         }
     406             : 
     407             :         // write out
     408           0 :         FILE * out = openOutFileWithRPartitePostfix ("benchmark_opmphm_mapping", rUniPar);
     409           0 :         if (!out)
     410             :         {
     411           0 :                 printExit ("open out file");
     412             :         }
     413             :         // print header
     414           0 :         fprintf (out, "trials");
     415           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     416             :         {
     417           0 :                 for (size_t cI = 0; cI < cCount; ++cI)
     418             :                 {
     419           0 :                         fprintf (out, ";n_%zuc_%f", n[nI], opmphmMinC (rUniPar) + c[cI]);
     420             :                 }
     421             :         }
     422           0 :         fprintf (out, "\n");
     423             :         // print data
     424           0 :         for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     425             :         {
     426           0 :                 fprintf (out, "%zu", mappingI + 1); // unshift, because 0 is not a result
     427           0 :                 for (size_t nI = 0; nI < nCount; ++nI)
     428             :                 {
     429           0 :                         for (size_t cI = 0; cI < cCount; ++cI)
     430             :                         {
     431           0 :                                 fprintf (out, ";%zu", results[nI * (cCount * maxMappings) + cI * maxMappings + mappingI]);
     432             :                         }
     433             :                 }
     434           0 :                 fprintf (out, "\n");
     435             :         }
     436             : 
     437             :         // cleanup
     438           0 :         for (size_t i = 0; i < numberOfKeySets; ++i)
     439             :         {
     440           0 :                 ksDel (keySetsCache[i]);
     441             :         }
     442           0 :         elektraFree (keySetsCache);
     443           0 :         fclose (out);
     444           0 :         elektraFree (keySetShapes);
     445           0 :         elektraFree (seeds);
     446           0 :         elektraFree (results);
     447           0 : }
     448             : 
     449             : /**
     450             :  * END ========================================================= Mapping =============================================================== END
     451             :  */
     452             : 
     453             : /**
     454             :  * START ============================================== Mapping with Optimization ==================================================== START
     455             :  *
     456             :  * This benchmark counts the opmphmMapping (...)  invocations until success, for each KeySet size.
     457             :  * First the KeySets are build, for every KeySet size (n) there are numberOfShapes * keySetsPerShape KeySets.
     458             :  * Then the benchmarking for every KeySet size (n) takes place, with a fixed set of seeds for the opmphmMapping (...) invocations.
     459             :  * At the end the results are written out in the following format:
     460             :  *
     461             :  * trials;n_%zur_%uc_%f;... (each n is unique)
     462             :  *
     463             :  * The number of needed seeds for this benchmarks is: nCount * numberOfShapes * keySetsPerShape (KeySets generation) + numberOfSeeds (tested
     464             :  * seeds)
     465             :  */
     466             : 
     467           0 : static void benchmarkMappingOpt (char * name)
     468             : {
     469             :         // create the n array
     470           0 :         const size_t nCount = 132;
     471           0 :         size_t * n = elektraMalloc (nCount * sizeof (size_t));
     472           0 :         if (!n)
     473             :         {
     474           0 :                 printExit ("malloc");
     475             :         }
     476             :         size_t controlCount = 0;
     477           0 :         for (size_t i = 2; i <= 38; ++i)
     478             :         {
     479           0 :                 n[controlCount] = i;
     480           0 :                 ++controlCount;
     481             :         }
     482           0 :         for (size_t i = 39; i <= 239; i = i + 5)
     483             :         {
     484           0 :                 n[controlCount] = i;
     485           0 :                 ++controlCount;
     486             :         }
     487           0 :         n[controlCount] = 240;
     488           0 :         ++controlCount;
     489           0 :         for (size_t i = 259; i <= 1279; i = i + 20)
     490             :         {
     491           0 :                 n[controlCount] = i;
     492           0 :                 ++controlCount;
     493             :         }
     494           0 :         n[controlCount] = 1280;
     495           0 :         ++controlCount;
     496           0 :         if (controlCount != nCount)
     497             :         {
     498           0 :                 printExit ("controlCount != nCount");
     499             :         }
     500             : 
     501           0 :         const size_t keySetsPerShape = 70;
     502           0 :         const size_t numberOfKeySets = nCount * numberOfShapes * keySetsPerShape;
     503             : 
     504           0 :         const size_t numberOfSeeds = 20000;
     505           0 :         const size_t maxMappings = 10; // the maximum trials for one opmphmMapping (...) invocation series.
     506             : 
     507             :         // init seed population, used for opmphmMapping (...) invocation.
     508           0 :         int32_t * seeds = elektraMalloc (numberOfSeeds * sizeof (int32_t));
     509           0 :         if (!seeds)
     510             :         {
     511           0 :                 printExit ("malloc");
     512             :         }
     513             :         // get seeds
     514           0 :         for (size_t i = 0; i < numberOfSeeds; ++i)
     515             :         {
     516           0 :                 if (getRandomSeed (&seeds[i]) != &seeds[i]) printExit ("Seed Parsing Error or feed me more seeds");
     517             :         }
     518             : 
     519             :         // init results
     520           0 :         size_t * results = elektraMalloc (nCount * maxMappings * sizeof (size_t));
     521           0 :         if (!results)
     522             :         {
     523           0 :                 printExit ("malloc");
     524             :         }
     525           0 :         memset (results, 0, nCount * maxMappings * sizeof (size_t));
     526             : 
     527             :         // Generate all KeySets
     528           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
     529           0 :         KeySet ** keySetsCache = elektraMalloc (numberOfKeySets * sizeof (KeySet *));
     530           0 :         if (!keySetsCache)
     531             :         {
     532           0 :                 printExit ("malloc");
     533             :         }
     534           0 :         printf ("KeySet Cache Build:\n");
     535           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     536             :         {
     537           0 :                 printf ("now at: %zu/%zu\r", nI + 1, nCount);
     538           0 :                 fflush (stdout);
     539           0 :                 for (size_t shapeI = 0; shapeI < numberOfShapes; ++shapeI)
     540             :                 {
     541           0 :                         for (size_t ksPshapeI = 0; ksPshapeI < keySetsPerShape; ++ksPshapeI)
     542             :                         {
     543             :                                 int32_t genSeed;
     544           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
     545           0 :                                 keySetsCache[nI * (numberOfShapes * keySetsPerShape) + shapeI * keySetsPerShape + ksPshapeI] =
     546           0 :                                         generateKeySet (n[nI], &genSeed, &keySetShapes[shapeI]);
     547             :                         }
     548             :                 }
     549             :         }
     550             : 
     551           0 :         printf ("\nRun Benchmark %s:\n", name);
     552             : 
     553             : #ifdef USE_OPENMP
     554             :         omp_set_num_threads (NUMBEROFTHREADS);
     555             :         // lock
     556             :         omp_lock_t writeLock;
     557             :         omp_init_lock (&writeLock);
     558             : #endif
     559             :         // split
     560             :         if (numberOfSeeds % NUMBEROFTHREADS != 0) printExit ("seeds % NUMBEROFTHREADS != 0");
     561           0 :         size_t partSize = numberOfSeeds / NUMBEROFTHREADS;
     562             : 
     563             :         // init threads local results
     564             :         size_t * localResults[NUMBEROFTHREADS];
     565           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     566             :         {
     567           0 :                 localResults[i] = elektraMalloc (nCount * maxMappings * sizeof (size_t));
     568           0 :                 if (!localResults[i])
     569             :                 {
     570           0 :                         printExit ("malloc");
     571             :                 }
     572             :         }
     573             : 
     574             :         // for all nCount
     575           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     576             :         {
     577           0 :                 printf ("now at: n = %zu/%zu\r", nI + 1, nCount);
     578           0 :                 fflush (stdout);
     579             :                 // OPMPHM for all threads
     580             :                 Opmphm * opmphms[NUMBEROFTHREADS];
     581             :                 OpmphmGraph * graphs[NUMBEROFTHREADS];
     582           0 :                 for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     583             :                 {
     584           0 :                         opmphms[i] = opmphmNew ();
     585           0 :                         if (!opmphms[i]) printExit ("opmphm");
     586           0 :                         uint8_t r = opmphmOptR (n[nI]);
     587           0 :                         graphs[i] = opmphmGraphNew (opmphms[i], r, n[nI], opmphmMinC (r) + opmphmOptC (n[nI]));
     588           0 :                         if (!graphs[i]) printExit ("graph");
     589             :                 }
     590             :                 // OPMPHM
     591             : 
     592             :                 // go through all KeySets from n
     593           0 :                 for (size_t ksCacheI = 0; ksCacheI < numberOfShapes * keySetsPerShape; ++ksCacheI)
     594             :                 {
     595           0 :                         KeySet * ks = keySetsCache[nI * (numberOfShapes * keySetsPerShape) + ksCacheI];
     596             : #ifdef USE_OPENMP
     597             : #pragma omp parallel
     598             : #endif
     599             :                         {
     600           0 :                                 size_t threadI = 0;
     601             :                                 // OPMPHM
     602             :                                 OpmphmInit init;
     603           0 :                                 init.getName = getString;
     604           0 :                                 init.data = (void **) (ks->array);
     605             : // OPMPHM
     606             : #ifdef USE_OPENMP
     607             :                                 threadI = omp_get_thread_num ();
     608             : #endif
     609             :                                 // reset local result
     610           0 :                                 memset (localResults[threadI], 0, nCount * maxMappings * sizeof (size_t));
     611             : 
     612             :                                 // try each seed part
     613           0 :                                 for (size_t seedI = threadI * partSize; seedI < (threadI + 1) * partSize; ++seedI)
     614             :                                 {
     615           0 :                                         size_t mappings = 0; // counts mapping invocations
     616             :                                         // OPMPHM
     617           0 :                                         init.initSeed = seeds[seedI];
     618             :                                         // fresh OpmphmGraph
     619           0 :                                         opmphmGraphClear (opmphms[threadI], graphs[threadI]);
     620             :                                         // do benchmark
     621             :                                         int ret;
     622             :                                         do
     623             :                                         {
     624           0 :                                                 ret = opmphmMapping (opmphms[threadI], graphs[threadI], &init, n[nI]);
     625           0 :                                                 ++mappings;
     626           0 :                                         } while (ret && mappings < maxMappings);
     627             :                                         // OPMPHM
     628           0 :                                         if (mappings < 1 || mappings > maxMappings)
     629             :                                         {
     630           0 :                                                 printExit ("benchmarkSeedRangeMappingCount: mappings out of range");
     631             :                                         }
     632             :                                         // check assignment
     633           0 :                                         if (nI < 5 && mappings != maxMappings)
     634             :                                         {
     635             :                                                 // assign
     636           0 :                                                 if (opmphmAssignment (opmphms[threadI], graphs[threadI], n[nI], 1))
     637             :                                                 {
     638           0 :                                                         printExit ("check assignment failed");
     639             :                                                 }
     640           0 :                                                 for (size_t i = 0; i < n[nI]; ++i)
     641             :                                                 {
     642           0 :                                                         if (i != opmphmLookup (opmphms[threadI], n[nI], init.getName (init.data[i])))
     643             :                                                         {
     644           0 :                                                                 printExit ("check assignment failed");
     645             :                                                         }
     646             :                                                 }
     647           0 :                                                 opmphmClear (opmphms[threadI]);
     648             :                                         }
     649             :                                         // save result
     650             :                                         // shift, because 0 not used
     651           0 :                                         --mappings;
     652           0 :                                         ++localResults[threadI][nI * maxMappings + mappings];
     653             :                                 }
     654             : #ifdef USE_OPENMP
     655             :                                 // write local to global
     656             :                                 omp_set_lock (&writeLock);
     657             : #endif
     658           0 :                                 for (size_t i = 0; i < nCount * maxMappings; ++i)
     659             :                                 {
     660           0 :                                         results[i] += localResults[threadI][i];
     661             :                                 }
     662             : #ifdef USE_OPENMP
     663             :                                 omp_unset_lock (&writeLock);
     664             : #endif
     665             :                         }
     666             :                 }
     667           0 :                 for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     668             :                 {
     669             :                         // OPMPHM
     670           0 :                         opmphmDel (opmphms[i]);
     671           0 :                         opmphmGraphDel (graphs[i]);
     672             :                         // OPMPHM
     673             :                 }
     674             :                 // end for all nCount
     675             :         }
     676             : #ifdef USE_OPENMP
     677             :         omp_destroy_lock (&writeLock);
     678             : #endif
     679           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     680             :         {
     681           0 :                 free (localResults[i]);
     682             :         }
     683           0 :         printf ("\n");
     684             : 
     685             :         /*
     686             :          * results sanity check
     687             :          *
     688             :          * each n should have in sum (numberOfShapes * keySetsPerShape) for each KeySet times (numberOfSeeds) seeds trials
     689             :          */
     690           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     691             :         {
     692             :                 size_t sum = 0;
     693           0 :                 for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     694             :                 {
     695           0 :                         sum += results[nI * maxMappings + mappingI];
     696             :                 }
     697           0 :                 if (sum != numberOfShapes * keySetsPerShape * numberOfSeeds)
     698             :                 {
     699           0 :                         printExit ("benchmarkSeedRangeMappingCount: results sanity check failed");
     700             :                 }
     701             :         }
     702             : 
     703             :         // write out
     704           0 :         FILE * out = fopen ("benchmark_opmphm_mapping_opt.csv", "w");
     705           0 :         if (!out)
     706             :         {
     707           0 :                 printExit ("open out file");
     708             :         }
     709             :         // print header
     710           0 :         fprintf (out, "trials");
     711           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     712             :         {
     713           0 :                 fprintf (out, ";n_%zur_%uc_%f", n[nI], opmphmOptR (n[nI]), opmphmMinC (opmphmOptR (n[nI])) + opmphmOptC (n[nI]));
     714             :         }
     715           0 :         fprintf (out, "\n");
     716             :         // print data
     717           0 :         for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     718             :         {
     719           0 :                 fprintf (out, "%zu", mappingI + 1); // unshift, because 0 is not a result
     720           0 :                 for (size_t nI = 0; nI < nCount; ++nI)
     721             :                 {
     722           0 :                         fprintf (out, ";%zu", results[nI * maxMappings + mappingI]);
     723             :                 }
     724           0 :                 fprintf (out, "\n");
     725             :         }
     726             : 
     727             :         // cleanup
     728           0 :         for (size_t i = 0; i < numberOfKeySets; ++i)
     729             :         {
     730           0 :                 ksDel (keySetsCache[i]);
     731             :         }
     732           0 :         elektraFree (n);
     733           0 :         elektraFree (keySetsCache);
     734           0 :         fclose (out);
     735           0 :         elektraFree (keySetShapes);
     736           0 :         elektraFree (seeds);
     737           0 :         elektraFree (results);
     738           0 : }
     739             : 
     740             : /**
     741             :  * END ================================================ Mapping with Optimization ====================================================== END
     742             :  */
     743             : 
     744             : /**
     745             :  * START ================================================== Mapping All Seeds ======================================================== START
     746             :  *
     747             :  * This benchmark counts the opmphmMapping (...)  invocations until success, for each KeySet size and all seeds.
     748             :  * First the KeySets are build, for every KeySet size (n). Then the benchmarking for every KeySet size (n) takes place,
     749             :  * the seeds start at 1 and go to ELEKTRARANDMAX - 1 = 2147483646.
     750             :  * At the end the results are written out in the following format:
     751             :  *
     752             :  * trials;n_%zur_%uc_%f;... (each n is unique)
     753             :  *
     754             :  * The number of needed seeds for this benchmarks is: nCount (KeySets generation)
     755             :  */
     756             : 
     757           0 : static void benchmarkMappingAllSeeds (char * name)
     758             : {
     759             :         // create the n array
     760           0 :         const size_t nCount = 7;
     761           0 :         size_t * n = elektraMalloc (nCount * sizeof (size_t));
     762           0 :         if (!n)
     763             :         {
     764           0 :                 printExit ("malloc");
     765             :         }
     766           0 :         n[0] = 9;
     767           0 :         n[1] = 29;
     768           0 :         n[2] = 49;
     769           0 :         n[3] = 69;
     770           0 :         n[4] = 89;
     771           0 :         n[5] = 109;
     772           0 :         n[6] = 129;
     773             : 
     774             :         // seeds limits
     775           0 :         const int32_t startSeed = 1;
     776           0 :         const int32_t endSeed = ELEKTRARANDMAX - 1; // = ELEKTRARANDMAX;
     777             : 
     778           0 :         const size_t maxMappings = 10; // the maximum trials for one opmphmMapping (...) invocation series.
     779             : 
     780             :         // init results
     781           0 :         size_t * results = elektraMalloc (nCount * maxMappings * sizeof (size_t));
     782           0 :         if (!results)
     783             :         {
     784           0 :                 printExit ("malloc");
     785             :         }
     786           0 :         memset (results, 0, nCount * maxMappings * sizeof (size_t));
     787             : 
     788             :         // Generate all KeySets
     789           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
     790           0 :         KeySet ** keySetsCache = elektraMalloc (nCount * sizeof (KeySet *));
     791           0 :         if (!keySetsCache)
     792             :         {
     793           0 :                 printExit ("malloc");
     794             :         }
     795           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     796             :         {
     797             :                 int32_t genSeed;
     798           0 :                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
     799           0 :                 keySetsCache[nI] = generateKeySet (n[nI], &genSeed, &keySetShapes[0]); // shape 0 is shapefConstBinary with 0 parents
     800             :         }
     801             : 
     802           0 :         printf ("\nRun Benchmark %s:\n", name);
     803             : 
     804             : #ifdef USE_OPENMP
     805             :         omp_set_num_threads (NUMBEROFTHREADS);
     806             :         // lock
     807             :         omp_lock_t writeLock;
     808             :         omp_init_lock (&writeLock);
     809             : #endif
     810             : 
     811             :         // split the job
     812             :         int32_t partIntervals[NUMBEROFTHREADS * 2];
     813           0 :         int32_t onePart = (endSeed - startSeed) / NUMBEROFTHREADS;
     814           0 :         int32_t iterateIntervals = startSeed;
     815           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     816             :         {
     817             :                 if (i == NUMBEROFTHREADS - 1)
     818             :                 {
     819             :                         // give last thread the remaining seeds
     820           0 :                         partIntervals[i * 2] = iterateIntervals;
     821           0 :                         partIntervals[(i * 2) + 1] = endSeed;
     822             :                 }
     823             :                 else
     824             :                 {
     825             :                         partIntervals[i * 2] = iterateIntervals;
     826             :                         partIntervals[(i * 2) + 1] = iterateIntervals + onePart - 1;
     827             :                         iterateIntervals += onePart;
     828             :                 }
     829             :         }
     830             : 
     831             :         // init threads local results
     832             :         size_t * localResults[NUMBEROFTHREADS];
     833           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     834             :         {
     835           0 :                 localResults[i] = elektraMalloc (nCount * maxMappings * sizeof (size_t));
     836           0 :                 if (!localResults[i])
     837             :                 {
     838           0 :                         printExit ("malloc");
     839             :                 }
     840             :         }
     841             : 
     842             :         // for all nCount
     843           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     844             :         {
     845             :                 // OPMPHM for all threads
     846             :                 Opmphm * opmphms[NUMBEROFTHREADS];
     847             :                 OpmphmGraph * graphs[NUMBEROFTHREADS];
     848           0 :                 for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     849             :                 {
     850           0 :                         opmphms[i] = opmphmNew ();
     851           0 :                         if (!opmphms[i]) printExit ("opmphm");
     852           0 :                         uint8_t r = opmphmOptR (n[nI]);
     853           0 :                         graphs[i] = opmphmGraphNew (opmphms[i], r, n[nI], opmphmMinC (r) + opmphmOptC (n[nI]));
     854           0 :                         if (!graphs[i]) printExit ("graph");
     855             :                 }
     856             :                 // OPMPHM
     857             : 
     858           0 :                 KeySet * ks = keySetsCache[nI];
     859             : #ifdef USE_OPENMP
     860             : #pragma omp parallel
     861             : #endif
     862             :                 {
     863           0 :                         size_t threadI = 0;
     864             :                         // OPMPHM
     865             :                         OpmphmInit init;
     866           0 :                         init.getName = getString;
     867           0 :                         init.data = (void **) (ks->array);
     868             :                         // OPMPHM
     869             : 
     870             : #ifdef USE_OPENMP
     871             :                         threadI = omp_get_thread_num ();
     872             : #endif
     873             :                         // reset local result
     874           0 :                         memset (localResults[threadI], 0, nCount * maxMappings * sizeof (size_t));
     875             : 
     876             :                         // try each seed part
     877           0 :                         for (int32_t seed = partIntervals[threadI * 2];
     878           0 :                              partIntervals[threadI * 2] <= seed && seed <= partIntervals[(threadI * 2) + 1]; ++seed)
     879             :                         {
     880           0 :                                 if (threadI == 0 && (seed % 1000) == 0)
     881             :                                 {
     882           0 :                                         printf ("now at: n = %zu/%zu and seed %i from %i\r", nI + 1, nCount, seed, partIntervals[1]);
     883           0 :                                         fflush (stdout);
     884             :                                 }
     885           0 :                                 size_t mappings = 0; // counts mapping invocations
     886             :                                 // OPMPHM
     887           0 :                                 init.initSeed = seed;
     888             :                                 // fresh OpmphmGraph
     889           0 :                                 opmphmGraphClear (opmphms[threadI], graphs[threadI]);
     890             :                                 // do benchmark
     891             :                                 int ret;
     892             :                                 do
     893             :                                 {
     894           0 :                                         ret = opmphmMapping (opmphms[threadI], graphs[threadI], &init, n[nI]);
     895           0 :                                         ++mappings;
     896           0 :                                 } while (ret && mappings < maxMappings);
     897             :                                 // OPMPHM
     898           0 :                                 if (mappings < 1 || mappings > maxMappings)
     899             :                                 {
     900           0 :                                         printExit ("benchmarkSeedRangeMappingCount: mappings out of range");
     901             :                                 }
     902             :                                 // save result
     903             :                                 // shift, because 0 not used
     904           0 :                                 --mappings;
     905           0 :                                 ++localResults[threadI][nI * maxMappings + mappings];
     906             :                         }
     907             : #ifdef USE_OPENMP
     908             :                         // write local to global
     909             :                         omp_set_lock (&writeLock);
     910             : #endif
     911           0 :                         for (size_t i = 0; i < nCount * maxMappings; ++i)
     912             :                         {
     913           0 :                                 results[i] += localResults[threadI][i];
     914             :                         }
     915             : #ifdef USE_OPENMP
     916             :                         omp_unset_lock (&writeLock);
     917             : #endif
     918             :                 }
     919           0 :                 for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     920             :                 {
     921             :                         // OPMPHM
     922           0 :                         opmphmDel (opmphms[i]);
     923           0 :                         opmphmGraphDel (graphs[i]);
     924             :                         // OPMPHM
     925             :                 }
     926             :                 // end for all nCount
     927             :         }
     928             : #ifdef USE_OPENMP
     929             :         omp_destroy_lock (&writeLock);
     930             : #endif
     931           0 :         for (size_t i = 0; i < NUMBEROFTHREADS; ++i)
     932             :         {
     933           0 :                 free (localResults[i]);
     934             :         }
     935           0 :         printf ("\n");
     936             : 
     937             :         /*
     938             :          * results sanity check
     939             :          *
     940             :          * each n should have in sum endSeed - startSeed + 1 trials
     941             :          */
     942           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     943             :         {
     944             :                 size_t sum = 0;
     945           0 :                 for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     946             :                 {
     947           0 :                         sum += results[nI * maxMappings + mappingI];
     948             :                 }
     949           0 :                 if (sum != (size_t) endSeed - startSeed + 1)
     950             :                 {
     951           0 :                         printExit ("benchmarkSeedRangeMappingCount: results sanity check failed");
     952             :                 }
     953             :         }
     954             : 
     955             :         // write out
     956           0 :         FILE * out = fopen ("benchmark_opmphm_mapping_allSeeds.csv", "w");
     957           0 :         if (!out)
     958             :         {
     959           0 :                 printExit ("open out file");
     960             :         }
     961             :         // print header
     962           0 :         fprintf (out, "trials");
     963           0 :         for (size_t nI = 0; nI < nCount; ++nI)
     964             :         {
     965           0 :                 fprintf (out, ";n_%zur_%uc_%f", n[nI], opmphmOptR (n[nI]), opmphmMinC (opmphmOptR (n[nI])) + opmphmOptC (n[nI]));
     966             :         }
     967           0 :         fprintf (out, "\n");
     968             :         // print data
     969           0 :         for (size_t mappingI = 0; mappingI < maxMappings; ++mappingI)
     970             :         {
     971           0 :                 fprintf (out, "%zu", mappingI + 1); // unshift, because 0 is not a result
     972           0 :                 for (size_t nI = 0; nI < nCount; ++nI)
     973             :                 {
     974           0 :                         fprintf (out, ";%zu", results[nI * maxMappings + mappingI]);
     975             :                 }
     976           0 :                 fprintf (out, "\n");
     977             :         }
     978             : 
     979             :         // cleanup
     980           0 :         for (size_t i = 0; i < nCount; ++i)
     981             :         {
     982           0 :                 ksDel (keySetsCache[i]);
     983             :         }
     984           0 :         elektraFree (n);
     985           0 :         elektraFree (keySetsCache);
     986           0 :         fclose (out);
     987           0 :         elektraFree (keySetShapes);
     988           0 :         elektraFree (results);
     989           0 : }
     990             : 
     991             : /**
     992             :  * END ==================================================== Mapping All Seeds ========================================================== END
     993             :  */
     994             : 
     995             : /**
     996             :  * START ================================================== OPMPHM Build Time ======================================================== START
     997             :  *
     998             :  * This benchmark measures the time of the OPMPHM build.
     999             :  * Uses all KeySet shapes except 6, for all n (KeySet size) a fixed set of seeds is used to build the OPMPHM.
    1000             :  * The keyset shape 6 is excluded, because previous evaluation had show that the results with that keyset shape
    1001             :  * where unusable, due to the unnatural long key names.
    1002             :  * For one n (KeySet size) ksPerN KeySets are used.
    1003             :  * The results are written out in the following format:
    1004             :  *
    1005             :  * n;ks;time
    1006             :  *
    1007             :  * The number of needed seeds for this benchmarks is: (numberOfShapes - 1) * ( numberOfSeeds + nCount * ksPerN )
    1008             :  */
    1009             : 
    1010             : /**
    1011             :  * @brief Measures the OPMPHM build numberOfRepeats time and returns median
    1012             :  *
    1013             :  * @param ks the KeySet
    1014             :  * @param repeats array to store repeated measurements
    1015             :  * @param numberOfRepeats fields in repeats
    1016             :  *
    1017             :  * @retval median time
    1018             :  */
    1019           0 : static size_t benchmarkOPMPHMBuildTimeMeasure (KeySet * ks, size_t * repeats, size_t numberOfRepeats)
    1020             : {
    1021           0 :         for (size_t repeatsI = 0; repeatsI < numberOfRepeats; ++repeatsI)
    1022             :         {
    1023             :                 // preparation for measurement
    1024             :                 struct timeval start;
    1025             :                 struct timeval end;
    1026           0 :                 Key * keySearchFor = ks->array[0]; // just some key
    1027             :                 Key * keyFound;
    1028             :                 // fresh OPMPHM
    1029           0 :                 if (ks->opmphm)
    1030             :                 {
    1031           0 :                         opmphmDel (ks->opmphm);
    1032           0 :                         ks->opmphm = NULL;
    1033             :                 }
    1034             : 
    1035             :                 // START MEASUREMENT
    1036           0 :                 __asm__("");
    1037           0 :                 gettimeofday (&start, 0);
    1038           0 :                 __asm__("");
    1039             : 
    1040           0 :                 keyFound = ksLookup (ks, keySearchFor, KDB_O_OPMPHM | KDB_O_NOCASCADING);
    1041             : 
    1042           0 :                 __asm__("");
    1043           0 :                 gettimeofday (&end, 0);
    1044           0 :                 __asm__("");
    1045             :                 // END MEASUREMENT
    1046             : 
    1047             :                 // save result
    1048           0 :                 repeats[repeatsI] = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    1049             : 
    1050             :                 // sanity check
    1051           0 :                 if (!opmphmIsBuild (ks->opmphm))
    1052             :                 {
    1053           0 :                         printExit ("Sanity Check Failed: OPMPHM not used");
    1054             :                 }
    1055           0 :                 if (keyFound != keySearchFor)
    1056             :                 {
    1057           0 :                         printExit ("Sanity Check Failed: found wrong Key");
    1058             :                 }
    1059             :         }
    1060             :         // sort repeats
    1061           0 :         qsort (repeats, numberOfRepeats, sizeof (size_t), cmpInteger);
    1062           0 :         return repeats[numberOfRepeats / 2]; // take median
    1063             : }
    1064             : 
    1065           0 : void benchmarkOPMPHMBuildTime (char * name)
    1066             : {
    1067           0 :         const size_t startN = 50;
    1068           0 :         const size_t stepN = 500;
    1069           0 :         const size_t endN = 20000;
    1070           0 :         const size_t ksPerN = 5;
    1071           0 :         const size_t numberOfSeeds = 51;
    1072           0 :         const size_t numberOfRepeats = 7;
    1073             : 
    1074             :         // check config
    1075             :         if (startN >= endN || startN == 0)
    1076             :         {
    1077             :                 printExit ("startN >= endN || startN == 0");
    1078             :         }
    1079             :         if (numberOfRepeats % 2 == 0)
    1080             :         {
    1081             :                 printExit ("numberOfRepeats is even");
    1082             :         }
    1083             :         if (numberOfSeeds % 2 == 0)
    1084             :         {
    1085             :                 printExit ("numberOfSeeds is even");
    1086             :         }
    1087             :         if (ksPerN % 2 == 0)
    1088             :         {
    1089             :                 printExit ("ksPerN is even");
    1090             :         }
    1091             : 
    1092             :         // calculate counts
    1093           0 :         size_t nCount = 0;
    1094           0 :         for (size_t nI = startN; nI <= endN; nI += stepN)
    1095             :         {
    1096           0 :                 ++nCount;
    1097             :         }
    1098             : 
    1099             :         // memory allocation and initialization
    1100             :         // init seeds for mapping step in ksLookup (...)
    1101           0 :         int32_t * seeds = elektraMalloc (numberOfSeeds * sizeof (int32_t));
    1102           0 :         if (!seeds)
    1103             :         {
    1104           0 :                 printExit ("malloc");
    1105             :         }
    1106             :         // init results
    1107           0 :         size_t * results = elektraMalloc (nCount * ksPerN * numberOfSeeds * sizeof (size_t));
    1108           0 :         if (!results)
    1109             :         {
    1110           0 :                 printExit ("malloc");
    1111             :         }
    1112             :         // init repeats
    1113           0 :         size_t * repeats = elektraMalloc (numberOfRepeats * sizeof (size_t));
    1114           0 :         if (!repeats)
    1115             :         {
    1116           0 :                 printExit ("malloc");
    1117             :         }
    1118             :         // init KeySetStorage
    1119           0 :         KeySet ** keySetStorage = elektraMalloc (ksPerN * sizeof (KeySet *));
    1120           0 :         if (!keySetStorage)
    1121             :         {
    1122           0 :                 printExit ("malloc");
    1123             :         }
    1124             : 
    1125             :         // get KeySet shapes
    1126           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
    1127             : 
    1128           0 :         printf ("Run Benchmark %s:\n", name);
    1129             : 
    1130             :         // for all KeySet shapes except 6
    1131           0 :         for (size_t shapeI = 0; shapeI < numberOfShapes; ++shapeI)
    1132             :         {
    1133           0 :                 if (shapeI == 6)
    1134             :                 {
    1135           0 :                         continue;
    1136             :                 }
    1137             :                 // get seeds for mapping step in ksLookup (...)
    1138           0 :                 for (size_t i = 0; i < numberOfSeeds; ++i)
    1139             :                 {
    1140           0 :                         if (getRandomSeed (&seeds[i]) != &seeds[i]) printExit ("Seed Parsing Error or feed me more seeds");
    1141             :                 }
    1142             : 
    1143           0 :                 KeySetShape * usedKeySetShape = &keySetShapes[shapeI];
    1144             : 
    1145             :                 // for all Ns
    1146           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1147             :                 {
    1148           0 :                         printf ("now at: shape = %zu/%zu n = %zu/%zu\r", shapeI + 1, numberOfShapes, nI, endN);
    1149           0 :                         fflush (stdout);
    1150             : 
    1151             :                         // generate KeySets
    1152             :                         int32_t genSeed;
    1153           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1154             :                         {
    1155           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1156           0 :                                 keySetStorage[ksI] = generateKeySet (nI, &genSeed, usedKeySetShape);
    1157             :                         }
    1158             : 
    1159             :                         // for all seeds
    1160           0 :                         for (size_t seedI = 0; seedI < numberOfSeeds; ++seedI)
    1161             :                         {
    1162             :                                 // set seed to return by elektraRandGetInitSeed () in the lookup
    1163           0 :                                 elektraRandBenchmarkInitSeed = seeds[seedI];
    1164             : 
    1165             :                                 // for all KeySets in the storage
    1166           0 :                                 for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1167             :                                 {
    1168             :                                         // measure
    1169           0 :                                         size_t res = benchmarkOPMPHMBuildTimeMeasure (keySetStorage[ksI], repeats, numberOfRepeats);
    1170             : 
    1171             :                                         // store res
    1172           0 :                                         results[((nI - startN) / stepN) * ksPerN * numberOfSeeds + ksI * numberOfSeeds + seedI] = res;
    1173             :                                 }
    1174             :                         }
    1175             : 
    1176             :                         // free ks
    1177           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1178             :                         {
    1179           0 :                                 ksDel (keySetStorage[ksI]);
    1180             :                         }
    1181             :                 }
    1182             : 
    1183             :                 // write out
    1184           0 :                 FILE * out = openOutFileWithRPartitePostfix ("benchmark_opmphm_build_time", shapeI);
    1185           0 :                 if (!out)
    1186             :                 {
    1187           0 :                         printExit ("open out file");
    1188             :                 }
    1189             :                 // print header
    1190           0 :                 fprintf (out, "n;ks;time\n");
    1191             :                 // print data
    1192           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1193             :                 {
    1194           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1195             :                         {
    1196           0 :                                 for (size_t seedI = 0; seedI < numberOfSeeds; ++seedI)
    1197             :                                 {
    1198           0 :                                         fprintf (out, "%zu;%zu;%zu\n", nI, ksI,
    1199           0 :                                                  results[((nI - startN) / stepN) * ksPerN * numberOfSeeds + ksI * numberOfSeeds + seedI]);
    1200             :                                 }
    1201             :                         }
    1202             :                 }
    1203             : 
    1204           0 :                 fclose (out);
    1205             :         }
    1206           0 :         printf ("\n");
    1207             : 
    1208           0 :         elektraFree (repeats);
    1209           0 :         elektraFree (keySetStorage);
    1210           0 :         elektraFree (keySetShapes);
    1211           0 :         elektraFree (results);
    1212           0 :         elektraFree (seeds);
    1213           0 : }
    1214             : 
    1215             : /**
    1216             :  * END ==================================================== OPMPHM Build Time ========================================================== END
    1217             :  */
    1218             : 
    1219             : /**
    1220             :  * START ================================================== OPMPHM Search Time ======================================================= START
    1221             :  *
    1222             :  * This benchmark measures the time of the OPMPHM search.
    1223             :  * Uses all KeySet shapes except 6, for one n (KeySet size) ksPerN KeySets are used.
    1224             :  * The keyset shape 6 is excluded, because previous evaluation had show that the results with that keyset shape
    1225             :  * where unusable, due to the unnatural long key names.
    1226             :  * Each measurement done with one KeySet is repeated numberOfRepeats time and summarized with the median.
    1227             :  * For one n (KeySet size) the ksPerN results are also summarized with the median.
    1228             :  * The results are written out in the following format:
    1229             :  *
    1230             :  * n;search_1;search_2;...;search_(numberOfSearches)
    1231             :  *
    1232             :  * The number of needed seeds for this benchmarks is: (numberOfShapes - 1) * nCount * ksPerN * (1  + searchesCount )
    1233             :  */
    1234             : 
    1235             : /**
    1236             :  * @brief Measures the OPMPHM search time, for searches random Keys, repeats the measurement numberOfRepeats time and returns the media.
    1237             :  *
    1238             :  * The OPMPHM build will be triggerd if KDB_OPMPHM is set!
    1239             :  *
    1240             :  * @param ks the KeySet
    1241             :  * @param searches the number of searches to make
    1242             :  * @param searchSeed the random seed used to determine the Keys to search
    1243             :  * @param option the options passed to the ksLookup (...)
    1244             :  * @param repeats array to store repeated measurements
    1245             :  * @param numberOfRepeats fields in repeats
    1246             :  *
    1247             :  * @retval median time
    1248             :  */
    1249           0 : static size_t benchmarkSearchTimeMeasure (KeySet * ks, size_t searches, int32_t searchSeed, option_t option, size_t * repeats,
    1250             :                                           size_t numberOfRepeats)
    1251             : {
    1252           0 :         if (option & KDB_O_OPMPHM)
    1253             :         {
    1254             :                 // trigger OPMPHM build if not build
    1255           0 :                 if (!opmphmIsBuild (ks->opmphm))
    1256             :                 {
    1257             :                         // set seed to return by elektraRandGetInitSeed () in the lookup
    1258           0 :                         elektraRandBenchmarkInitSeed = searchSeed;
    1259           0 :                         (void) ksLookup (ks, ks->array[0], KDB_O_OPMPHM | KDB_O_NOCASCADING);
    1260           0 :                         if (!opmphmIsBuild (ks->opmphm))
    1261             :                         {
    1262           0 :                                 printExit ("trigger OPMPHM build");
    1263             :                         }
    1264             :                 }
    1265             :         }
    1266           0 :         for (size_t repeatsI = 0; repeatsI < numberOfRepeats; ++repeatsI)
    1267             :         {
    1268             :                 // sanity checks
    1269           0 :                 if (option & KDB_O_OPMPHM)
    1270             :                 {
    1271           0 :                         if (!opmphmIsBuild (ks->opmphm))
    1272             :                         {
    1273           0 :                                 printExit ("Sanity Check Failed: OPMPHM not here");
    1274             :                         }
    1275             :                 }
    1276             :                 else
    1277             :                 {
    1278           0 :                         if (ks->opmphm)
    1279             :                         {
    1280           0 :                                 printExit ("Sanity Check Failed: OPMPHM here");
    1281             :                         }
    1282             :                 }
    1283             : 
    1284             :                 // preparation for measurement
    1285             :                 struct timeval start;
    1286             :                 struct timeval end;
    1287             :                 Key * keyFound;
    1288           0 :                 int32_t actualSearchSeed = searchSeed;
    1289             : 
    1290             :                 // START MEASUREMENT
    1291           0 :                 __asm__("");
    1292           0 :                 gettimeofday (&start, 0);
    1293           0 :                 __asm__("");
    1294             : 
    1295           0 :                 for (size_t s = 1; s <= searches; ++s)
    1296             :                 {
    1297           0 :                         keyFound = ksLookup (ks, ks->array[actualSearchSeed % ks->size], option);
    1298           0 :                         if (!keyFound || keyFound != ks->array[actualSearchSeed % ks->size])
    1299             :                         {
    1300           0 :                                 printExit ("Sanity Check Failed: found wrong Key");
    1301             :                         }
    1302           0 :                         elektraRand (&actualSearchSeed);
    1303             :                 }
    1304             : 
    1305           0 :                 __asm__("");
    1306           0 :                 gettimeofday (&end, 0);
    1307           0 :                 __asm__("");
    1308             :                 // END MEASUREMENT
    1309             : 
    1310             :                 // sanity checks
    1311           0 :                 if (option & KDB_O_OPMPHM)
    1312             :                 {
    1313           0 :                         if (!opmphmIsBuild (ks->opmphm))
    1314             :                         {
    1315           0 :                                 printExit ("Sanity Check Failed: OPMPHM not here");
    1316             :                         }
    1317             :                 }
    1318             :                 else
    1319             :                 {
    1320           0 :                         if (ks->opmphm)
    1321             :                         {
    1322           0 :                                 printExit ("Sanity Check Failed: OPMPHM here");
    1323             :                         }
    1324             :                 }
    1325             : 
    1326             :                 // save result
    1327           0 :                 repeats[repeatsI] = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    1328             :         }
    1329             :         // sort repeats
    1330           0 :         qsort (repeats, numberOfRepeats, sizeof (size_t), cmpInteger);
    1331           0 :         return repeats[numberOfRepeats / 2]; // take median
    1332             : }
    1333             : 
    1334             : /**
    1335             :  * @brief Common part of search time benchmarks, used by benchmarkOPMPHMSearchTime and benchmarkBinarySearchTime.
    1336             :  *
    1337             :  * @param outFileName the output file name
    1338             :  * @param option the option to pass to the ksLookup (...)
    1339             :  */
    1340           0 : static void benchmarkSearchTime (char * name, char * outFileName, option_t option)
    1341             : {
    1342           0 :         const size_t startN = 50;
    1343           0 :         const size_t stepN = 500;
    1344           0 :         const size_t endN = 20000;
    1345           0 :         const size_t ksPerN = 3;
    1346           0 :         const size_t numberOfRepeats = 7;
    1347           0 :         const size_t startSearches = 500;
    1348           0 :         const size_t stepSearches = 500;
    1349           0 :         const size_t endSearches = 32000;
    1350             : 
    1351             :         // check config
    1352             :         if (startN >= endN || startN == 0)
    1353             :         {
    1354             :                 printExit ("startN >= endN || startN == 0");
    1355             :         }
    1356             :         if (numberOfRepeats % 2 == 0)
    1357             :         {
    1358             :                 printExit ("numberOfRepeats is even");
    1359             :         }
    1360             :         if (ksPerN % 2 == 0)
    1361             :         {
    1362             :                 printExit ("ksPerN is even");
    1363             :         }
    1364             : 
    1365             :         // calculate counts
    1366           0 :         size_t nCount = 0;
    1367           0 :         for (size_t nI = startN; nI <= endN; nI += stepN)
    1368             :         {
    1369           0 :                 ++nCount;
    1370             :         }
    1371             :         size_t searchesCount = 0;
    1372           0 :         for (size_t searchesI = startSearches; searchesI <= endSearches; searchesI += stepSearches)
    1373             :         {
    1374           0 :                 ++searchesCount;
    1375             :         }
    1376             : 
    1377             :         // memory allocation and initialization
    1378             :         // init results
    1379           0 :         size_t * results = elektraMalloc (nCount * searchesCount * sizeof (size_t));
    1380           0 :         if (!results)
    1381             :         {
    1382           0 :                 printExit ("malloc");
    1383             :         }
    1384             :         // init repeats
    1385           0 :         size_t * repeats = elektraMalloc (numberOfRepeats * sizeof (size_t));
    1386           0 :         if (!repeats)
    1387             :         {
    1388           0 :                 printExit ("malloc");
    1389             :         }
    1390             :         // init partialResult
    1391           0 :         size_t * partialResult = elektraMalloc (ksPerN * searchesCount * sizeof (size_t));
    1392           0 :         if (!partialResult)
    1393             :         {
    1394           0 :                 printExit ("malloc");
    1395             :         }
    1396             :         // init KeySetStorage
    1397           0 :         KeySet ** keySetStorage = elektraMalloc (ksPerN * sizeof (KeySet *));
    1398           0 :         if (!keySetStorage)
    1399             :         {
    1400           0 :                 printExit ("malloc");
    1401             :         }
    1402             : 
    1403             :         // get KeySet shapes
    1404           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
    1405             : 
    1406           0 :         printf ("Run Benchmark %s:\n", name);
    1407             : 
    1408             :         // for all KeySet shapes except 6
    1409           0 :         for (size_t shapeI = 0; shapeI < numberOfShapes; ++shapeI)
    1410             :         {
    1411           0 :                 if (shapeI == 6)
    1412             :                 {
    1413           0 :                         continue;
    1414             :                 }
    1415           0 :                 KeySetShape * usedKeySetShape = &keySetShapes[shapeI];
    1416             : 
    1417             :                 // for all Ns
    1418           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1419             :                 {
    1420           0 :                         printf ("now at: shape = %zu/%zu n = %zu/%zu\r", shapeI + 1, numberOfShapes, nI, endN);
    1421           0 :                         fflush (stdout);
    1422             : 
    1423             :                         // generate KeySets
    1424             :                         int32_t genSeed;
    1425           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1426             :                         {
    1427           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1428           0 :                                 keySetStorage[ksI] = generateKeySet (nI, &genSeed, usedKeySetShape);
    1429             :                         }
    1430             : 
    1431             :                         // for all number of searches
    1432           0 :                         for (size_t searchesI = startSearches; searchesI <= endSearches; searchesI += stepSearches)
    1433             :                         {
    1434           0 :                                 int32_t searchSeed = 1;
    1435           0 :                                 if (getRandomSeed (&searchSeed) != &searchSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1436             : 
    1437             :                                 // for all KeySets in the storage
    1438           0 :                                 for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1439             :                                 {
    1440             :                                         // measure
    1441           0 :                                         size_t res = benchmarkSearchTimeMeasure (keySetStorage[ksI], searchesI, searchSeed, option, repeats,
    1442             :                                                                                  numberOfRepeats);
    1443             :                                         // save partial result to summarize it with median
    1444           0 :                                         partialResult[((searchesI - startSearches) / stepSearches) * ksPerN + ksI] = res;
    1445             :                                 }
    1446             :                         }
    1447             :                         // sort partialResult and take median as final result
    1448           0 :                         for (size_t searchesI = 0; searchesI < searchesCount; ++searchesI)
    1449             :                         {
    1450           0 :                                 qsort (&partialResult[searchesI * ksPerN], ksPerN, sizeof (size_t), cmpInteger);
    1451           0 :                                 results[((nI - startN) / stepN) * searchesCount + searchesI] =
    1452           0 :                                         partialResult[searchesI * ksPerN + (ksPerN / 2)];
    1453             :                         }
    1454             : 
    1455             :                         // free ks
    1456           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1457             :                         {
    1458           0 :                                 ksDel (keySetStorage[ksI]);
    1459             :                         }
    1460             :                 }
    1461             : 
    1462             :                 // write out
    1463           0 :                 FILE * out = openOutFileWithRPartitePostfix (outFileName, shapeI);
    1464           0 :                 if (!out)
    1465             :                 {
    1466           0 :                         printExit ("open out file");
    1467             :                 }
    1468             :                 // print header
    1469           0 :                 fprintf (out, "n");
    1470           0 :                 for (size_t searchesI = startSearches; searchesI <= endSearches; searchesI += stepSearches)
    1471             :                 {
    1472           0 :                         fprintf (out, ";search_%zu", searchesI);
    1473             :                 }
    1474           0 :                 fprintf (out, "\n");
    1475             :                 // print data
    1476           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1477             :                 {
    1478           0 :                         fprintf (out, "%zu", nI);
    1479           0 :                         for (size_t searchesI = startSearches; searchesI <= endSearches; searchesI += stepSearches)
    1480             :                         {
    1481           0 :                                 fprintf (out, ";%zu",
    1482           0 :                                          results[((nI - startN) / stepN) * searchesCount + ((searchesI - startSearches) / stepSearches)]);
    1483             :                         }
    1484           0 :                         fprintf (out, "\n");
    1485             :                 }
    1486             : 
    1487           0 :                 fclose (out);
    1488             :         }
    1489           0 :         printf ("\n");
    1490             : 
    1491           0 :         elektraFree (repeats);
    1492           0 :         elektraFree (partialResult);
    1493           0 :         elektraFree (keySetStorage);
    1494           0 :         elektraFree (keySetShapes);
    1495           0 :         elektraFree (results);
    1496           0 : }
    1497             : 
    1498           0 : void benchmarkOPMPHMSearchTime (char * name)
    1499             : {
    1500           0 :         benchmarkSearchTime (name, "benchmark_opmphm_search_time", KDB_O_OPMPHM | KDB_O_NOCASCADING);
    1501           0 : }
    1502             : 
    1503             : /**
    1504             :  * END ==================================================== OPMPHM Search Time ========================================================= END
    1505             :  */
    1506             : 
    1507             : /**
    1508             :  * START ================================================= Binary search Time ======================================================== START
    1509             :  *
    1510             :  * This benchmark measures the time of the binary search.
    1511             :  * Uses all KeySet shapes except 6, for one n (KeySet size) ksPerN KeySets are used.
    1512             :  * The keyset shape 6 is excluded, because previous evaluation had show that the results with that keyset shape
    1513             :  * where unusable, due to the unnatural long key names.
    1514             :  * Each measurement done with one KeySet is repeated numberOfRepeats time and summarized with the median.
    1515             :  * For one n (KeySet size) the ksPerN results are also summarized with the median.
    1516             :  * The results are written out in the following format:
    1517             :  *
    1518             :  * n;search_1;search_2;...;search_(numberOfSearches)
    1519             :  *
    1520             :  * The number of needed seeds for this benchmarks is: (numberOfShapes - 1) * nCount * ksPerN * (1  + searchesCount )
    1521             :  */
    1522             : 
    1523           0 : static void benchmarkBinarySearchTime (char * name)
    1524             : {
    1525           0 :         benchmarkSearchTime (name, "benchmark_binary_search_time", KDB_O_NOCASCADING);
    1526           0 : }
    1527             : 
    1528             : /**
    1529             :  * END =================================================== Binary search Time ========================================================== END
    1530             :  */
    1531             : 
    1532             : /**
    1533             :  * START ================================================= hsearch Build Time ======================================================== START
    1534             :  *
    1535             :  * This benchmark measures the time of the hsearch build.
    1536             :  * For one n (KeySet size) ksPerN KeySets are used, with different loads.
    1537             :  * This benchmark has a 10 strike policy, when 10 time the measured time is over 10000 the next KeySet shape is handled.
    1538             :  * The results are written out in the following format:
    1539             :  *
    1540             :  * n;ks;load;time
    1541             :  *
    1542             :  * The number of needed seeds for this benchmarks is: (numberOfShapes - 1) * nCount * ksPerN
    1543             :  */
    1544             : 
    1545             : // clang-format off
    1546             : // format bug
    1547             : #ifdef HAVE_HSEARCHR
    1548             : // clang-format on
    1549             : 
    1550             : /**
    1551             :  * @brief Measures the hsearch build numberOfRepeats time and returns median
    1552             :  *
    1553             :  * @param ks the KeySet
    1554             :  * @param nI the KeySet size
    1555             :  * @param load the load
    1556             :  * @param repeats array to store repeated measurements
    1557             :  * @param numberOfRepeats fields in repeats
    1558             :  *
    1559             :  * @retval median time
    1560             :  */
    1561           0 : static size_t benchmarkHsearchBuildTimeMeasure (KeySet * ks, size_t nI, double load, size_t * repeats, size_t numberOfRepeats)
    1562             : {
    1563           0 :         for (size_t repeatsI = 0; repeatsI < numberOfRepeats; ++repeatsI)
    1564             :         {
    1565             :                 // preparation for measurement
    1566             :                 struct timeval start;
    1567             :                 struct timeval end;
    1568             :                 Key * key;
    1569           0 :                 ksRewind (ks);
    1570             :                 ENTRY e;
    1571             :                 ENTRY * ep;
    1572             :                 // fresh htab
    1573           0 :                 struct hsearch_data * htab = elektraCalloc (sizeof (struct hsearch_data));
    1574           0 :                 if (!htab)
    1575             :                 {
    1576           0 :                         printExit ("calloc");
    1577             :                 }
    1578             : 
    1579             :                 // START MEASUREMENT
    1580           0 :                 __asm__("");
    1581           0 :                 gettimeofday (&start, 0);
    1582           0 :                 __asm__("");
    1583             : 
    1584           0 :                 if (!hcreate_r (nI / load, htab))
    1585             :                 {
    1586           0 :                         printExit ("hcreate_r");
    1587             :                 }
    1588             : 
    1589           0 :                 while ((key = ksNext (ks)))
    1590             :                 {
    1591           0 :                         e.key = (char *) keyName (key);
    1592           0 :                         e.data = key;
    1593           0 :                         if (!hsearch_r (e, ENTER, &ep, htab))
    1594             :                         {
    1595           0 :                                 printExit ("hsearch_r");
    1596             :                         }
    1597             :                 }
    1598             : 
    1599           0 :                 __asm__("");
    1600           0 :                 gettimeofday (&end, 0);
    1601           0 :                 __asm__("");
    1602             :                 // END MEASUREMENT
    1603             : 
    1604             :                 // save result
    1605           0 :                 repeats[repeatsI] = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    1606             : 
    1607             :                 // sanity check
    1608           0 :                 ksRewind (ks);
    1609           0 :                 while ((key = ksNext (ks)))
    1610             :                 {
    1611           0 :                         e.key = (char *) keyName (key);
    1612           0 :                         if (!hsearch_r (e, FIND, &ep, htab))
    1613             :                         {
    1614           0 :                                 printExit ("Sanity Check Failed: hsearch can not find element");
    1615             :                         }
    1616             :                 }
    1617             : 
    1618           0 :                 hdestroy_r (htab);
    1619           0 :                 elektraFree (htab);
    1620             :         }
    1621             :         // sort repeats
    1622           0 :         qsort (repeats, numberOfRepeats, sizeof (size_t), cmpInteger);
    1623           0 :         return repeats[numberOfRepeats / 2]; // take median
    1624             : }
    1625             : 
    1626           0 : void benchmarkHsearchBuildTime (char * name)
    1627             : {
    1628           0 :         const size_t startN = 50;
    1629           0 :         const size_t stepN = 500;
    1630           0 :         const size_t endN = 20000;
    1631           0 :         const size_t ksPerN = 5;
    1632           0 :         const size_t numberOfRepeats = 7;
    1633           0 :         const size_t maxStrikes = 10;
    1634           0 :         const size_t strikeLimit = 10000;
    1635           0 :         const size_t numberOfLoads = 4;
    1636           0 :         double * loads = malloc (sizeof (double) * numberOfLoads);
    1637           0 :         if (!loads)
    1638             :         {
    1639           0 :                 printExit ("malloc");
    1640             :         }
    1641           0 :         loads[0] = 1;
    1642           0 :         loads[1] = 0.75;
    1643           0 :         loads[2] = 0.5;
    1644           0 :         loads[3] = 0.25;
    1645             : 
    1646             :         // check config
    1647             :         if (startN >= endN || startN == 0)
    1648             :         {
    1649             :                 printExit ("startN >= endN || startN == 0");
    1650             :         }
    1651             :         if (numberOfRepeats % 2 == 0)
    1652             :         {
    1653             :                 printExit ("numberOfRepeats is even");
    1654             :         }
    1655             :         if (ksPerN % 2 == 0)
    1656             :         {
    1657             :                 printExit ("ksPerN is even");
    1658             :         }
    1659             : 
    1660             :         // calculate counts
    1661           0 :         size_t nCount = 0;
    1662           0 :         for (size_t nI = startN; nI <= endN; nI += stepN)
    1663             :         {
    1664           0 :                 ++nCount;
    1665             :         }
    1666             : 
    1667             :         // memory allocation and initialization
    1668             :         // init results
    1669           0 :         size_t * results = elektraMalloc (nCount * ksPerN * numberOfLoads * sizeof (size_t));
    1670           0 :         if (!results)
    1671             :         {
    1672           0 :                 printExit ("malloc");
    1673             :         }
    1674             :         // init repeats
    1675           0 :         size_t * repeats = elektraMalloc (numberOfRepeats * sizeof (size_t));
    1676           0 :         if (!repeats)
    1677             :         {
    1678           0 :                 printExit ("malloc");
    1679             :         }
    1680             :         // init KeySetStorage
    1681           0 :         KeySet ** keySetStorage = elektraMalloc (ksPerN * sizeof (KeySet *));
    1682           0 :         if (!keySetStorage)
    1683             :         {
    1684           0 :                 printExit ("malloc");
    1685             :         }
    1686             : 
    1687             :         // get KeySet shapes
    1688           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
    1689             : 
    1690           0 :         printf ("Run Benchmark %s:\n", name);
    1691             : 
    1692             :         // for all KeySet shapes except 6
    1693           0 :         for (size_t shapeI = 0; shapeI < numberOfShapes; ++shapeI)
    1694             :         {
    1695           0 :                 if (shapeI == 6)
    1696             :                 {
    1697           0 :                         continue;
    1698             :                 }
    1699           0 :                 KeySetShape * usedKeySetShape = &keySetShapes[shapeI];
    1700           0 :                 size_t strikes = 0;
    1701             : 
    1702             :                 // for all Ns
    1703           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1704             :                 {
    1705           0 :                         printf ("now at: shape = %zu/%zu n = %zu/%zu\r", shapeI + 1, numberOfShapes, nI, endN);
    1706           0 :                         fflush (stdout);
    1707             : 
    1708             :                         // generate KeySets
    1709             :                         int32_t genSeed;
    1710           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1711             :                         {
    1712           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1713           0 :                                 keySetStorage[ksI] = generateKeySet (nI, &genSeed, usedKeySetShape);
    1714             :                         }
    1715             : 
    1716             :                         // for all loads
    1717           0 :                         for (size_t loadI = 0; loadI < numberOfLoads; ++loadI)
    1718             :                         {
    1719             :                                 // for all KeySets in the storage
    1720           0 :                                 for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1721             :                                 {
    1722             :                                         // measure
    1723           0 :                                         size_t res = benchmarkHsearchBuildTimeMeasure (keySetStorage[ksI], nI, loads[loadI], repeats,
    1724             :                                                                                        numberOfRepeats);
    1725             :                                         // strike policy
    1726           0 :                                         if (res > strikeLimit)
    1727             :                                         {
    1728           0 :                                                 ++strikes;
    1729           0 :                                                 if (strikes >= maxStrikes)
    1730             :                                                 {
    1731           0 :                                                         ksI = ksPerN;
    1732           0 :                                                         loadI = numberOfLoads;
    1733           0 :                                                         nI = endN + 1;
    1734           0 :                                                         printf ("shape %zu is out!\n", shapeI);
    1735             :                                                 }
    1736             :                                         }
    1737             :                                         else
    1738             :                                         {
    1739           0 :                                                 strikes = 0;
    1740             :                                                 // save only non strike values
    1741           0 :                                                 results[((nI - startN) / stepN) * ksPerN * numberOfLoads + ksI * numberOfLoads + loadI] =
    1742             :                                                         res;
    1743             :                                         }
    1744             :                                 }
    1745             :                         }
    1746             : 
    1747             :                         // free ks
    1748           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1749             :                         {
    1750           0 :                                 ksDel (keySetStorage[ksI]);
    1751             :                         }
    1752             :                 }
    1753             : 
    1754             :                 // write out
    1755           0 :                 FILE * out = openOutFileWithRPartitePostfix ("benchmark_hsearch_build_time", shapeI);
    1756           0 :                 if (!out)
    1757             :                 {
    1758           0 :                         printExit ("open out file");
    1759             :                 }
    1760             :                 // print header
    1761           0 :                 fprintf (out, "n;ks;load;time\n");
    1762             :                 // print data
    1763           0 :                 for (size_t nI = startN; nI <= endN; nI += stepN)
    1764             :                 {
    1765           0 :                         for (size_t ksI = 0; ksI < ksPerN; ++ksI)
    1766             :                         {
    1767           0 :                                 for (size_t loadI = 0; loadI < numberOfLoads; ++loadI)
    1768             :                                 {
    1769           0 :                                         fprintf (out, "%zu;%zu;%f;%zu\n", nI, ksI, loads[loadI],
    1770           0 :                                                  results[((nI - startN) / stepN) * ksPerN * numberOfLoads + ksI * numberOfLoads + loadI]);
    1771             :                                 }
    1772             :                         }
    1773             :                 }
    1774             : 
    1775           0 :                 fclose (out);
    1776             :         }
    1777           0 :         printf ("\n");
    1778             : 
    1779           0 :         elektraFree (repeats);
    1780           0 :         elektraFree (keySetStorage);
    1781           0 :         elektraFree (loads);
    1782           0 :         elektraFree (keySetShapes);
    1783           0 :         elektraFree (results);
    1784           0 : }
    1785             : 
    1786             : #endif
    1787             : 
    1788             : /**
    1789             :  * END =================================================== hsearch Build Time ========================================================== END
    1790             :  */
    1791             : 
    1792             : /**
    1793             :  * START =================================================== Prediction Time ========================================================= START
    1794             :  *
    1795             :  * This benchmark measures the time from `numberOfSequences` lookup sequences, with the modified branch predictor and the binary search.
    1796             :  * All KeySet shapes except 6 where used.
    1797             :  * The keyset shape 6 is excluded, because previous evaluation had show that the results with that keyset shape
    1798             :  * where unusable, due to the unnatural long key names.
    1799             :  * For all `n` `patternsPerN` lookup patterns are created. With a length of `numberOfSequences`.
    1800             :  * The KeySet shapes rotate through the lookup patterns.
    1801             :  * Two entries of the pattern entries use one seed (31 bit), this works because max n  is 10000.
    1802             :  * log_2 (opmphmPredictorWorthOpmphm(10000)) * 2) < 15 bit
    1803             :  * log_2 (15000) * 2) < 15 bit
    1804             :  *
    1805             :  * n;predictiontime;binarysearchtime
    1806             :  *
    1807             :  * The number of needed seeds for this benchmarks is: nCount * patternsPerN * ( numberOfSequences/2 + 1 + numberOfSequences )
    1808             :  */
    1809             : 
    1810           0 : static void benchmarkPredictionTime (char * name)
    1811             : {
    1812           0 :         const size_t numberOfRepeats = 5;
    1813           0 :         const size_t numberOfSequences = 66;
    1814           0 :         const size_t patternsPerN = 999;
    1815             :         // create the n array
    1816           0 :         const size_t nCount = 35;
    1817           0 :         size_t * n = elektraMalloc (nCount * sizeof (size_t));
    1818           0 :         if (!n)
    1819             :         {
    1820           0 :                 printExit ("malloc");
    1821             :         }
    1822             :         size_t controlCount = 0;
    1823           0 :         for (size_t i = 100; i < 1000; i += 100)
    1824             :         {
    1825           0 :                 n[controlCount] = i;
    1826           0 :                 ++controlCount;
    1827             :         }
    1828           0 :         for (size_t i = 1000; i < 5000; i += 200)
    1829             :         {
    1830           0 :                 n[controlCount] = i;
    1831           0 :                 ++controlCount;
    1832             :         }
    1833           0 :         for (size_t i = 5000; i <= 10000; i += 1000)
    1834             :         {
    1835           0 :                 n[controlCount] = i;
    1836           0 :                 ++controlCount;
    1837             :         }
    1838             : 
    1839             :         // check config
    1840           0 :         if (controlCount != nCount)
    1841             :         {
    1842           0 :                 printExit ("controlCount != nCount");
    1843             :         }
    1844             :         if (numberOfRepeats % 2 == 0)
    1845             :         {
    1846             :                 printExit ("numberOfRepeats is even");
    1847             :         }
    1848             :         if (patternsPerN % (numberOfShapes - 1) == 0)
    1849             :         {
    1850             :                 printExit ("not all shapes used equally");
    1851             :         }
    1852             : 
    1853             :         // memory allocation and initialization
    1854             :         // init results
    1855           0 :         size_t * results = elektraMalloc (nCount * patternsPerN * 2 * sizeof (size_t)); // 2 prediction and binary search
    1856           0 :         if (!results)
    1857             :         {
    1858           0 :                 printExit ("malloc");
    1859             :         }
    1860             :         // init repeats
    1861           0 :         size_t * repeats = elektraMalloc (numberOfRepeats * sizeof (size_t));
    1862           0 :         if (!repeats)
    1863             :         {
    1864           0 :                 printExit ("malloc");
    1865             :         }
    1866             :         // init seeds
    1867           0 :         int32_t * seeds = elektraMalloc (numberOfSequences * sizeof (int32_t));
    1868           0 :         if (!seeds)
    1869             :         {
    1870           0 :                 printExit ("malloc");
    1871             :         }
    1872             :         // init pattern
    1873           0 :         size_t * pattern = elektraMalloc (numberOfSequences * sizeof (size_t));
    1874           0 :         if (!pattern)
    1875             :         {
    1876           0 :                 printExit ("malloc");
    1877             :         }
    1878             : 
    1879             :         // get KeySet shapes
    1880           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
    1881             : 
    1882           0 :         printf ("Run Benchmark %s:\n", name);
    1883             : 
    1884             :         // for all n
    1885           0 :         for (size_t nI = 0; nI < nCount; ++nI)
    1886             :         {
    1887             :                 // for all pattern per n
    1888           0 :                 for (size_t pI = 0; pI < patternsPerN; ++pI)
    1889             :                 {
    1890           0 :                         printf ("now at: n = %zu/%zu pattern = %zu/%zu \r", nI + 1, nCount, pI + 1, patternsPerN);
    1891           0 :                         fflush (stdout);
    1892             :                         // create pattern, always two entries with one seed
    1893           0 :                         for (size_t s = 0; s < numberOfSequences; s += 2)
    1894             :                         {
    1895           0 :                                 int32_t genSeed = 0;
    1896           0 :                                 if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1897             :                                 // 15 bit each of the 31 bit seed
    1898           0 :                                 size_t sequnceLength1 = (genSeed >> 15) & 0x7FFF;
    1899           0 :                                 size_t sequnceLength0 = genSeed & 0x7FFF;
    1900           0 :                                 sequnceLength1 = sequnceLength1 % (opmphmPredictorWorthOpmphm (n[nI]) * 2 - 1);
    1901           0 :                                 sequnceLength0 = sequnceLength0 % (opmphmPredictorWorthOpmphm (n[nI]) * 2 - 1);
    1902           0 :                                 pattern[s + 1] = sequnceLength1 + 1;
    1903           0 :                                 pattern[s] = sequnceLength0 + 1;
    1904             :                         }
    1905             :                         // rotate through all KeySet shapes, except 6
    1906           0 :                         size_t shapeI = patternsPerN % (numberOfShapes - 1);
    1907             :                         if (shapeI == 6)
    1908             :                         {
    1909             :                                 ++shapeI;
    1910             :                         }
    1911           0 :                         KeySetShape * usedKeySetShape = &keySetShapes[shapeI];
    1912             : 
    1913             :                         // generate KeySet
    1914           0 :                         int32_t genSeed = 0;
    1915           0 :                         if (getRandomSeed (&genSeed) != &genSeed) printExit ("Seed Parsing Error or feed me more seeds");
    1916           0 :                         KeySet * ks = generateKeySet (n[nI], &genSeed, usedKeySetShape);
    1917             : 
    1918             :                         // get seeds for OPMPHM
    1919           0 :                         for (size_t s = 0; s < numberOfSequences; ++s)
    1920             :                         {
    1921           0 :                                 if (getRandomSeed (&seeds[s]) != &seeds[s]) printExit ("Seed Parsing Error or feed me more seeds");
    1922             :                         }
    1923             : 
    1924             :                         size_t resultPredition;
    1925             :                         size_t resultBinarySearch;
    1926             : 
    1927             :                         // benchmark prediction
    1928             : 
    1929             :                         // repeat measurement numberOfRepeats time
    1930           0 :                         for (size_t repeatsI = 0; repeatsI < numberOfRepeats; ++repeatsI)
    1931             :                         {
    1932             :                                 // preparation for measurement
    1933             :                                 struct timeval start;
    1934             :                                 struct timeval end;
    1935             :                                 Key * keyFound;
    1936             : 
    1937             :                                 // START MEASUREMENT
    1938           0 :                                 __asm__("");
    1939           0 :                                 gettimeofday (&start, 0);
    1940           0 :                                 __asm__("");
    1941             : 
    1942             :                                 // for all sequences
    1943           0 :                                 for (size_t s = 0; s < numberOfSequences; ++s)
    1944             :                                 {
    1945             :                                         // seed used for key to lookup and OPMPHM
    1946           0 :                                         int32_t searchHashSeed = seeds[s];
    1947             :                                         // set seed to return by elektraRandGetInitSeed () in the lookup, in case of hashing
    1948           0 :                                         elektraRandBenchmarkInitSeed = searchHashSeed;
    1949             : 
    1950             :                                         // do the lookups
    1951           0 :                                         for (size_t lookups = 0; lookups < pattern[s]; ++lookups)
    1952             :                                         {
    1953           0 :                                                 keyFound = ksLookup (ks, ks->array[searchHashSeed % ks->size], KDB_O_NOCASCADING);
    1954           0 :                                                 if (!keyFound || keyFound != ks->array[searchHashSeed % ks->size])
    1955             :                                                 {
    1956           0 :                                                         printExit ("Sanity Check Failed: found wrong Key");
    1957             :                                                 }
    1958           0 :                                                 elektraRand (&searchHashSeed);
    1959             :                                         }
    1960           0 :                                         if (!ks->opmphmPredictor)
    1961             :                                         {
    1962           0 :                                                 printExit ("Sanity Check Failed: no predictor used");
    1963             :                                         }
    1964             :                                         // simulate data change
    1965           0 :                                         ks->flags |= KS_FLAG_NAME_CHANGE;
    1966           0 :                                         if (ks->opmphm) opmphmClear (ks->opmphm);
    1967             :                                 }
    1968             : 
    1969           0 :                                 __asm__("");
    1970           0 :                                 gettimeofday (&end, 0);
    1971           0 :                                 __asm__("");
    1972             :                                 // END MEASUREMENT
    1973             : 
    1974             :                                 // save result
    1975           0 :                                 repeats[repeatsI] = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    1976             :                         }
    1977             :                         // sort repeats
    1978           0 :                         qsort (repeats, numberOfRepeats, sizeof (size_t), cmpInteger);
    1979           0 :                         resultPredition = repeats[numberOfRepeats / 2];
    1980             : 
    1981             :                         // benchmark binary search
    1982             : 
    1983             :                         // repeat measurement numberOfRepeats time
    1984           0 :                         for (size_t repeatsI = 0; repeatsI < numberOfRepeats; ++repeatsI)
    1985             :                         {
    1986             :                                 // preparation for measurement
    1987             :                                 struct timeval start;
    1988             :                                 struct timeval end;
    1989             :                                 Key * keyFound;
    1990             : 
    1991             :                                 // START MEASUREMENT
    1992           0 :                                 __asm__("");
    1993           0 :                                 gettimeofday (&start, 0);
    1994           0 :                                 __asm__("");
    1995             : 
    1996             :                                 // for all sequences
    1997           0 :                                 for (size_t s = 0; s < numberOfSequences; ++s)
    1998             :                                 {
    1999             :                                         // seed used for key to lookup and OPMPHM
    2000           0 :                                         int32_t searchHashSeed = seeds[s];
    2001             : 
    2002             :                                         // do the lookups
    2003           0 :                                         for (size_t lookups = 0; lookups < pattern[s]; ++lookups)
    2004             :                                         {
    2005           0 :                                                 keyFound = ksLookup (ks, ks->array[searchHashSeed % ks->size],
    2006             :                                                                      KDB_O_NOCASCADING | KDB_O_BINSEARCH);
    2007           0 :                                                 if (!keyFound || keyFound != ks->array[searchHashSeed % ks->size])
    2008             :                                                 {
    2009           0 :                                                         printExit ("Sanity Check Failed: found wrong Key");
    2010             :                                                 }
    2011           0 :                                                 elektraRand (&searchHashSeed);
    2012             :                                         }
    2013             :                                 }
    2014             : 
    2015           0 :                                 __asm__("");
    2016           0 :                                 gettimeofday (&end, 0);
    2017           0 :                                 __asm__("");
    2018             :                                 // END MEASUREMENT
    2019             : 
    2020             :                                 // save result
    2021           0 :                                 repeats[repeatsI] = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    2022             :                         }
    2023             :                         // sort repeats
    2024           0 :                         qsort (repeats, numberOfRepeats, sizeof (size_t), cmpInteger);
    2025           0 :                         resultBinarySearch = repeats[numberOfRepeats / 2];
    2026             : 
    2027           0 :                         results[nI * patternsPerN * 2 + pI * 2] = resultPredition;
    2028           0 :                         results[nI * patternsPerN * 2 + pI * 2 + 1] = resultBinarySearch;
    2029             : 
    2030           0 :                         ksDel (ks);
    2031             :                 }
    2032             :         }
    2033           0 :         printf ("\n");
    2034             :         // write out
    2035           0 :         FILE * out = openOutFileWithRPartitePostfix ("benchmark_prediction_time", opmphmPredictorHistoryMask >> 4); // shift 16 to 8 bit
    2036           0 :         if (!out)
    2037             :         {
    2038           0 :                 printExit ("open out file");
    2039             :         }
    2040             :         // print header
    2041           0 :         fprintf (out, "n;predictiontime;binarysearchtime\n");
    2042           0 :         for (size_t nI = 0; nI < nCount; ++nI)
    2043             :         {
    2044           0 :                 for (size_t pI = 0; pI < patternsPerN; ++pI)
    2045             :                 {
    2046           0 :                         size_t predictiontime = results[nI * patternsPerN * 2 + pI * 2];
    2047           0 :                         size_t binarysearchtime = results[nI * patternsPerN * 2 + pI * 2 + 1];
    2048           0 :                         fprintf (out, "%zu;%zu;%zu\n", n[nI], predictiontime, binarysearchtime);
    2049             :                 }
    2050             :         }
    2051           0 :         fclose (out);
    2052             : 
    2053           0 :         elektraFree (n);
    2054           0 :         elektraFree (keySetShapes);
    2055           0 :         elektraFree (results);
    2056           0 :         elektraFree (repeats);
    2057           0 :         elektraFree (pattern);
    2058           0 :         elektraFree (seeds);
    2059           0 : }
    2060             : 
    2061             : /**
    2062             :  * END ===================================================== Prediction Time =========================================================== END
    2063             :  */
    2064             : 
    2065             : /**
    2066             :  * START ================================================= Prints all KeySetShapes =================================================== START
    2067             :  */
    2068             : 
    2069           0 : static void benchmarkPrintAllKeySetShapes (char * name)
    2070             : {
    2071           0 :         printf ("%s\n", name);
    2072           0 :         const size_t n = 30;
    2073           0 :         int32_t seed = 47658589;
    2074           0 :         KeySetShape * keySetShapes = getKeySetShapes ();
    2075           0 :         for (size_t shapeId = 0; shapeId < numberOfShapes; ++shapeId)
    2076             :         {
    2077           0 :                 int32_t s = seed;
    2078             :                 //~ timeInit ();
    2079           0 :                 KeySet * ks = generateKeySet (n, &s, &keySetShapes[shapeId]);
    2080             :                 //~ timePrint ("generateKeySet:");
    2081             :                 // print KS
    2082             :                 if (1)
    2083             :                 {
    2084           0 :                         printf (" ======================= shapeId %zu =======================\n\n", shapeId);
    2085             :                         Key * key;
    2086           0 :                         ksRewind (ks);
    2087           0 :                         while ((key = ksNext (ks)))
    2088             :                         {
    2089           0 :                                 printf ("%s\n", keyName (key));
    2090             :                         }
    2091           0 :                         printf ("\n ======================== size %zd ========================\n\n", ksGetSize (ks));
    2092             :                 }
    2093           0 :                 ksDel (ks);
    2094             :         }
    2095           0 :         elektraFree (keySetShapes);
    2096           0 : }
    2097             : 
    2098             : /**
    2099             :  * END =================================================== Prints all KeySetShapes ===================================================== END
    2100             :  */
    2101             : 
    2102           0 : int main (int argc, char ** argv)
    2103             : {
    2104             :         // define all benchmarks
    2105           0 :         size_t benchmarksCount = 9;
    2106             : #ifdef HAVE_HSEARCHR
    2107             :         // hsearchbuildtime
    2108           0 :         ++benchmarksCount;
    2109             : #endif
    2110           0 :         Benchmark * benchmarks = elektraMalloc (benchmarksCount * sizeof (Benchmark));
    2111           0 :         if (!benchmarks)
    2112             :         {
    2113           0 :                 printExit ("malloc");
    2114             :         }
    2115             : 
    2116             :         // hashfunctiontime
    2117           0 :         char * benchmarkNameHashFunctionTime = "hashfunctiontime";
    2118           0 :         benchmarks[0].name = benchmarkNameHashFunctionTime;
    2119           0 :         benchmarks[0].benchmarkF = benchmarkHashFunctionTime;
    2120           0 :         benchmarks[0].numberOfSeedsNeeded = 32;
    2121             :         // mapping
    2122           0 :         char * benchmarkNameMapping = "mapping";
    2123           0 :         benchmarks[1].name = benchmarkNameMapping;
    2124           0 :         benchmarks[1].benchmarkF = benchmarkMapping;
    2125           0 :         benchmarks[1].numberOfSeedsNeeded = 12400;
    2126             :         // mapping_opt
    2127           0 :         char * benchmarkNameMappingOpt = "mapping_opt";
    2128           0 :         benchmarks[2].name = benchmarkNameMappingOpt;
    2129           0 :         benchmarks[2].benchmarkF = benchmarkMappingOpt;
    2130           0 :         benchmarks[2].numberOfSeedsNeeded = 93920;
    2131             :         // mapping_allseeds
    2132           0 :         char * benchmarkNameMappingAllSeeds = "mapping_allseeds";
    2133           0 :         benchmarks[3].name = benchmarkNameMappingAllSeeds;
    2134           0 :         benchmarks[3].benchmarkF = benchmarkMappingAllSeeds;
    2135           0 :         benchmarks[3].numberOfSeedsNeeded = 7;
    2136             :         // printallkeysetshapes
    2137           0 :         char * benchmarkNamePrintAllKeySetShapes = "printallkeysetshapes";
    2138           0 :         benchmarks[4].name = benchmarkNamePrintAllKeySetShapes;
    2139           0 :         benchmarks[4].benchmarkF = benchmarkPrintAllKeySetShapes;
    2140           0 :         benchmarks[4].numberOfSeedsNeeded = 0;
    2141             :         // opmphmbuildtime
    2142           0 :         char * benchmarkNameOpmphmBuildTime = "opmphmbuildtime";
    2143           0 :         benchmarks[5].name = benchmarkNameOpmphmBuildTime;
    2144           0 :         benchmarks[5].benchmarkF = benchmarkOPMPHMBuildTime;
    2145           0 :         benchmarks[5].numberOfSeedsNeeded = 1757;
    2146             :         // opmphmsearchtime
    2147           0 :         char * benchmarkNameOpmphmSearchTime = "opmphmsearchtime";
    2148           0 :         benchmarks[6].name = benchmarkNameOpmphmSearchTime;
    2149           0 :         benchmarks[6].benchmarkF = benchmarkOPMPHMSearchTime;
    2150           0 :         benchmarks[6].numberOfSeedsNeeded = 54600;
    2151             :         // binarysearchtime
    2152           0 :         char * benchmarkNameBinarySearchTime = "binarysearchtime";
    2153           0 :         benchmarks[7].name = benchmarkNameBinarySearchTime;
    2154           0 :         benchmarks[7].benchmarkF = benchmarkBinarySearchTime;
    2155           0 :         benchmarks[7].numberOfSeedsNeeded = 54600;
    2156             :         // predictiontime
    2157           0 :         char * benchmarkNamePredictionTime = "predictiontime";
    2158           0 :         benchmarks[8].name = benchmarkNamePredictionTime;
    2159           0 :         benchmarks[8].benchmarkF = benchmarkPredictionTime;
    2160           0 :         benchmarks[8].numberOfSeedsNeeded = 3496500;
    2161             : #ifdef HAVE_HSEARCHR
    2162             :         // hsearchbuildtime
    2163           0 :         char * benchmarkNameHsearchBuildTime = "hsearchbuildtime";
    2164           0 :         benchmarks[benchmarksCount - 1].name = benchmarkNameHsearchBuildTime;
    2165           0 :         benchmarks[benchmarksCount - 1].benchmarkF = benchmarkHsearchBuildTime;
    2166           0 :         benchmarks[benchmarksCount - 1].numberOfSeedsNeeded = 1400;
    2167             : #endif
    2168             : 
    2169             :         // run benchmark
    2170           0 :         if (argc == 1)
    2171             :         {
    2172           0 :                 fprintf (stderr, "Usage: cat <fileWithSeeds> | %s <benchmark>\n", argv[0]);
    2173           0 :                 fprintf (stderr, "\nUse the generate-seeds script to generate <fileWithSeeds>, number of seeds according to:\n\n");
    2174           0 :                 fprintf (stderr, "%-20s %10s\n", "<benchmark>", "seeds");
    2175           0 :                 for (size_t i = 0; i < benchmarksCount; ++i)
    2176             :                 {
    2177           0 :                         fprintf (stderr, "%-20s %10zu\n", benchmarks[i].name, benchmarks[i].numberOfSeedsNeeded);
    2178             :                 }
    2179           0 :                 elektraFree (benchmarks);
    2180           0 :                 return EXIT_FAILURE;
    2181             :         }
    2182           0 :         for (size_t i = 0; i < benchmarksCount; ++i)
    2183             :         {
    2184           0 :                 if (!strncmp (benchmarks[i].name, argv[1], strlen (argv[1])))
    2185             :                 {
    2186           0 :                         benchmarks[i].benchmarkF (benchmarks[i].name);
    2187           0 :                         elektraFree (benchmarks);
    2188           0 :                         return EXIT_SUCCESS;
    2189             :                 }
    2190             :         }
    2191           0 :         fprintf (stderr, "Error: %s is not a benchmark\n", argv[1]);
    2192           0 :         fprintf (stderr, "Available benchmarks:\n");
    2193           0 :         for (size_t i = 0; i < benchmarksCount; ++i)
    2194             :         {
    2195           0 :                 fprintf (stderr, "* %s\n", benchmarks[i].name);
    2196             :         }
    2197           0 :         elektraFree (benchmarks);
    2198           0 :         return EXIT_FAILURE;
    2199             : }
    2200             : 
    2201             : /**
    2202             :  * Benchmark helpers
    2203             :  */
    2204             : 
    2205             : /**
    2206             :  * @brief Read a seed from STDIN.
    2207             :  *
    2208             :  * @param seed storage for the read in seed
    2209             :  *
    2210             :  * @retval int32_t * on success
    2211             :  * @retval NULL on read or parse error
    2212             :  */
    2213           0 : static int32_t * getRandomSeed (int32_t * seed)
    2214             : {
    2215             :         // read from stdin
    2216             :         char data[10 + 2]; // min = 0, max = 2^32 - 1, len(2^32 - 1) = 10 + '\n' + '\0'
    2217           0 :         if (fgets (data, 12, stdin) != data)
    2218             :         {
    2219             :                 return NULL;
    2220             :         }
    2221             :         // eliminate newline
    2222             :         char * c;
    2223           0 :         for (c = data; *c != '\n'; ++c)
    2224             :                 ;
    2225           0 :         *c = '\0';
    2226             :         // prevent empty lines
    2227           0 :         if (strlen (data) == 0)
    2228             :         {
    2229             :                 return NULL;
    2230             :         }
    2231             :         // convert to int
    2232             :         char * pEnd;
    2233           0 :         *seed = strtol (data, &pEnd, 10);
    2234           0 :         if (*pEnd != '\0')
    2235             :         {
    2236             :                 return NULL;
    2237             :         }
    2238           0 :         return seed;
    2239             : }
    2240             : 
    2241             : /**
    2242             :  * @brief Opens file with OPMPHMR_PARTITE postfix.
    2243             :  *
    2244             :  * supports OPMPHMTUPLE < 100
    2245             :  *
    2246             :  * @param name name of the file
    2247             :  *
    2248             :  * @retval FILE * on success
    2249             :  * @retval NULL on error
    2250             :  */
    2251           0 : static FILE * openOutFileWithRPartitePostfix (const char * name, uint8_t r)
    2252           0 : {
    2253           0 :         const char * const format = "%u.csv";
    2254           0 :         char formatData[strlen (name) + strlen (format) + 1];
    2255           0 :         char filename[strlen (name) + strlen (format) + 1];
    2256           0 :         strcpy (formatData, name);
    2257           0 :         strcpy (&formatData[strlen (name)], format);
    2258           0 :         sprintf (filename, formatData, r);
    2259           0 :         FILE * out = fopen (filename, "w");
    2260           0 :         if (!out)
    2261             :         {
    2262             :                 return NULL;
    2263             :         }
    2264           0 :         return out;
    2265             : }
    2266             : 
    2267           0 : static const char * getString (void * data)
    2268             : {
    2269           0 :         return keyName ((Key *) data);
    2270             : }
    2271             : 
    2272             : /**
    2273             :  * @brief Power function.
    2274             :  *
    2275             :  * @param p basis
    2276             :  * @param q exponent
    2277             :  *
    2278             :  * @retval size_t p^q
    2279             :  */
    2280             : static size_t getPower (size_t p, size_t q)
    2281             : {
    2282           0 :         size_t result = 1;
    2283           0 :         for (size_t t = 0; t < q; ++t)
    2284             :         {
    2285           0 :                 result *= p;
    2286             :         }
    2287             :         return result;
    2288             : }
    2289             : 
    2290             : /**
    2291             :  * @brief comparison between integers suitable as qsort callback.
    2292             :  *
    2293             :  * @param a first integer
    2294             :  * @param b second integer
    2295             :  *
    2296             :  */
    2297           0 : static int cmpInteger (const void * a, const void * b)
    2298             : {
    2299           0 :         if (*(size_t *) a < *(size_t *) b)
    2300             :         {
    2301             :                 return -1;
    2302             :         }
    2303           0 :         else if (*(size_t *) a > *(size_t *) b)
    2304             :         {
    2305             :                 return 1;
    2306             :         }
    2307             :         else
    2308             :         {
    2309           0 :                 return 0;
    2310             :         }
    2311             : }
    2312             : 
    2313             : /**
    2314             :  * The Key Set shapes
    2315             :  */
    2316             : 
    2317             : 
    2318             : /**
    2319             :  * every key name is unique and goes 1 level deep
    2320             :  */
    2321           0 : static void shapefConstBinary (const size_t initSize ELEKTRA_UNUSED, size_t size ELEKTRA_UNUSED, size_t level ELEKTRA_UNUSED,
    2322             :                                int32_t * seed ELEKTRA_UNUSED, KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2323             : {
    2324           0 :         ret->label = 0;
    2325           0 :         ret->subKeys = 0;
    2326           0 : }
    2327             : /**
    2328             :  * binary tree
    2329             :  */
    2330           0 : static void shapefBinaryBranch (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2331             :                                 KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2332             : {
    2333           0 :         size_t subKeys = 2;
    2334           0 :         ret->label = 0;
    2335           0 :         if (getPower (subKeys, level) > initSize)
    2336             :         {
    2337           0 :                 ret->subKeys = 0;
    2338             :         }
    2339             :         else
    2340             :         {
    2341           0 :                 ret->subKeys = subKeys;
    2342             :         }
    2343           0 : }
    2344             : /**
    2345             :  * every parent has n/branchfactor children
    2346             :  */
    2347           0 : static void shapefDynamicBranch (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2348             :                                  KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2349             : {
    2350           0 :         size_t branchRatio = 9;
    2351           0 :         ret->label = 0;
    2352           0 :         size_t subKeys = (initSize / branchRatio);
    2353           0 :         if (subKeys < 2)
    2354             :         {
    2355           0 :                 subKeys = 2;
    2356             :         }
    2357           0 :         if (getPower (subKeys, level) > initSize)
    2358             :         {
    2359           0 :                 ret->subKeys = 0;
    2360             :         }
    2361             :         else
    2362             :         {
    2363           0 :                 ret->subKeys = subKeys;
    2364             :         }
    2365           0 : }
    2366             : /**
    2367             :  * all key names have a common start, startLevel length
    2368             :  */
    2369           0 : static void shapefLateDynamicBranch (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2370             :                                      KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2371             : {
    2372           0 :         size_t startLevel = 5;
    2373           0 :         size_t branchRatio = 9;
    2374           0 :         ret->label = 0;
    2375           0 :         if (level < startLevel)
    2376             :         {
    2377           0 :                 ret->subKeys = 1;
    2378           0 :                 return;
    2379             :         }
    2380           0 :         level -= startLevel;
    2381           0 :         size_t subKeys = (initSize / branchRatio);
    2382           0 :         if (subKeys < 2)
    2383             :         {
    2384           0 :                 subKeys = 2;
    2385             :         }
    2386           0 :         if (getPower (subKeys, level) > initSize)
    2387             :         {
    2388           0 :                 ret->subKeys = 0;
    2389             :         }
    2390             :         else
    2391             :         {
    2392           0 :                 ret->subKeys = subKeys;
    2393             :         }
    2394             : }
    2395             : /**
    2396             :  * all key names have a common start and end
    2397             :  */
    2398           0 : static void * shapeCommonStartEndInit (void)
    2399             : {
    2400           0 :         uint8_t * data = elektraMalloc (sizeof (uint8_t));
    2401           0 :         if (!data)
    2402             :         {
    2403             :                 return NULL;
    2404             :         }
    2405           0 :         *data = 0;
    2406           0 :         return data;
    2407             : }
    2408           0 : static void shapeCommonStartEndDel (void * data)
    2409             : {
    2410           0 :         elektraFree (data);
    2411           0 : }
    2412           0 : static void shapefCommonStartEnd (const size_t initSize ELEKTRA_UNUSED, size_t size, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2413             :                                   KsShapeFunctionReturn * ret, void * data)
    2414             : {
    2415           0 :         size_t notCommonLevel = 4;
    2416           0 :         size_t maxLevel = 10;
    2417           0 :         if (level < notCommonLevel)
    2418             :         {
    2419             :                 // creates common start
    2420           0 :                 ret->subKeys = 1;
    2421           0 :                 ret->label = 0;
    2422             :         }
    2423           0 :         else if (notCommonLevel == level)
    2424             :         {
    2425             :                 // creates level with different names
    2426           0 :                 ret->subKeys = size + 1;
    2427           0 :                 ret->label = 0;
    2428             :         }
    2429           0 :         else if (level > notCommonLevel)
    2430             :         {
    2431           0 :                 uint8_t * isLabelSet = data;
    2432           0 :                 if (!*isLabelSet)
    2433             :                 {
    2434             :                         // creates common end
    2435           0 :                         if (level == notCommonLevel + 1)
    2436             :                         {
    2437             :                                 // set label
    2438           0 :                                 ret->label = 1;
    2439           0 :                                 ret->subKeys = 1;
    2440             :                         }
    2441           0 :                         else if (level == maxLevel)
    2442             :                         {
    2443             :                                 // end of deep key
    2444           0 :                                 ret->label = 0;
    2445           0 :                                 ret->subKeys = 0;
    2446           0 :                                 *isLabelSet = 1;
    2447             :                         }
    2448             :                         else
    2449             :                         {
    2450             :                                 // create deep key
    2451           0 :                                 ret->label = 0;
    2452           0 :                                 ret->subKeys = 1;
    2453             :                         }
    2454             :                 }
    2455             :                 else
    2456             :                 {
    2457             :                         // use common end
    2458           0 :                         ret->subKeys = -1;
    2459           0 :                         ret->label = 1;
    2460             :                 }
    2461             :         }
    2462           0 : }
    2463             : /**
    2464             :  * modules, level 1 keys same, one level 2 key stores the modules. Like system/elektra.
    2465             :  */
    2466           0 : static void * shapeModulesInit (void)
    2467             : {
    2468             :         // three boolean flags if the respective label where set, the fourth counts from 1 to 3 for label assignment
    2469           0 :         void * data = elektraMalloc (4 * sizeof (uint8_t));
    2470           0 :         if (!data)
    2471             :         {
    2472             :                 return NULL;
    2473             :         }
    2474           0 :         uint8_t * d = data;
    2475           0 :         d[0] = 0;
    2476           0 :         d[1] = 0;
    2477           0 :         d[2] = 0;
    2478           0 :         d[3] = 1;
    2479           0 :         return data;
    2480             : }
    2481           0 : static void shapeModulesDel (void * data)
    2482             : {
    2483           0 :         elektraFree (data);
    2484           0 : }
    2485           0 : static void shapefModules (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2486             :                            KsShapeFunctionReturn * ret, void * data)
    2487             : {
    2488             :         // label 1 5 subKeys
    2489             :         // label 2 10 subKeys
    2490             :         // label 3 20 subKeys
    2491           0 :         ssize_t modulesKeys[3] = { 5, 10, 15 };
    2492           0 :         uint8_t * d = data;
    2493           0 :         uint8_t * firstSet = &d[0];
    2494           0 :         uint8_t * secondSet = &d[1];
    2495           0 :         uint8_t * thirdSet = &d[2];
    2496           0 :         uint8_t * assign = &d[3];
    2497           0 :         if (level == 1)
    2498             :         {
    2499             :                 // common start, simulates elektra in system/elektra
    2500           0 :                 ret->subKeys = 1;
    2501           0 :                 ret->label = 0;
    2502             :         }
    2503           0 :         else if (level == 2)
    2504             :         {
    2505             :                 // common name, simulates modules in system/elektra/modules
    2506             :                 // calculates how many modules have space
    2507           0 :                 ret->subKeys = 0;
    2508           0 :                 ssize_t remainingSize = initSize;
    2509           0 :                 uint8_t isSpace = 1;
    2510           0 :                 uint8_t l = 0;
    2511           0 :                 while (isSpace)
    2512             :                 {
    2513           0 :                         if (remainingSize - modulesKeys[l] < 0)
    2514             :                         {
    2515             :                                 isSpace = 0;
    2516             :                         }
    2517             :                         else
    2518             :                         {
    2519           0 :                                 remainingSize -= modulesKeys[l];
    2520           0 :                                 l = (l + 1) % 3;
    2521           0 :                                 ++ret->subKeys;
    2522             :                         }
    2523             :                 }
    2524             :                 // add solo keys
    2525           0 :                 ret->subKeys += remainingSize;
    2526           0 :                 ret->label = 0;
    2527             :         }
    2528           0 :         else if (level == 3)
    2529             :         {
    2530             :                 // give each modules ret->subKeys * 5 subKeys
    2531           0 :                 if (!*firstSet)
    2532             :                 {
    2533           0 :                         ret->subKeys = 1;
    2534           0 :                         ret->label = 1;
    2535           0 :                         *firstSet = 1;
    2536             :                 }
    2537           0 :                 else if (!*secondSet)
    2538             :                 {
    2539           0 :                         ret->subKeys = 2;
    2540           0 :                         ret->label = 2;
    2541           0 :                         *secondSet = 1;
    2542             :                 }
    2543           0 :                 else if (!*thirdSet)
    2544             :                 {
    2545           0 :                         ret->subKeys = 3;
    2546           0 :                         ret->label = 3;
    2547           0 :                         *thirdSet = 1;
    2548             :                 }
    2549             :                 else
    2550             :                 {
    2551             :                         // assign
    2552           0 :                         ret->subKeys = -1;
    2553           0 :                         ret->label = *assign;
    2554           0 :                         *assign = (*assign % 3) + 1;
    2555             :                 }
    2556             :         }
    2557           0 :         else if (level == 4)
    2558             :         {
    2559             :                 // the 5 in ret->subKeys * 5
    2560           0 :                 ret->subKeys = 5;
    2561           0 :                 ret->label = 0;
    2562             :         }
    2563             :         else
    2564             :         {
    2565             :                 // terminate keys
    2566           0 :                 ret->subKeys = 0;
    2567           0 :                 ret->label = 0;
    2568             :         }
    2569           0 : }
    2570             : /**
    2571             :  * always wider, subKeys are incremented by one every level
    2572             :  */
    2573           0 : static void shapefWide (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2574             :                         KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2575             : {
    2576           0 :         ret->label = 0;
    2577           0 :         size_t startSubKeys = 2;
    2578             :         // determine to which level it is possible to go
    2579           0 :         size_t l = 0; // level 0 should have 2 subs
    2580           0 :         size_t keysOnLevel = startSubKeys;
    2581           0 :         while (keysOnLevel <= initSize)
    2582             :         {
    2583           0 :                 ++l;
    2584           0 :                 keysOnLevel *= startSubKeys + l;
    2585             :         }
    2586           0 :         if (level < l)
    2587             :         {
    2588           0 :                 ret->subKeys = startSubKeys + level;
    2589             :         }
    2590             :         else
    2591             :         {
    2592           0 :                 ret->subKeys = 0;
    2593             :         }
    2594           0 : }
    2595             : /**
    2596             :  * always tighter, subKeys are decrementing by one every level till two is reached
    2597             :  */
    2598           0 : static void shapefTight (const size_t initSize, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
    2599             :                          KsShapeFunctionReturn * ret, void * data ELEKTRA_UNUSED)
    2600             : {
    2601           0 :         ret->label = 0;
    2602           0 :         size_t startSubKeys = 2;
    2603             :         // determine to which level it is possible to go
    2604           0 :         size_t l = 0; // level 0 should have 2 subs
    2605           0 :         size_t keysOnLevel = startSubKeys;
    2606           0 :         while (keysOnLevel <= initSize)
    2607             :         {
    2608           0 :                 ++l;
    2609           0 :                 keysOnLevel *= startSubKeys + l;
    2610             :         }
    2611           0 :         if (level < l)
    2612             :         {
    2613           0 :                 ret->subKeys = startSubKeys + l - level - 1;
    2614             :         }
    2615             :         else
    2616             :         {
    2617           0 :                 ret->subKeys = 0;
    2618             :         }
    2619           0 : }
    2620             : 
    2621             : /**
    2622             :  * @brief Set the shape functions and parameters together to get the KeySetShape population.
    2623             :  *
    2624             :  * @retval KeySetShape * on success
    2625             :  */
    2626           0 : static KeySetShape * getKeySetShapes (void)
    2627             : {
    2628           0 :         KeySetShape * out = elektraMalloc (sizeof (KeySetShape) * numberOfShapes);
    2629           0 :         if (!out) printExit ("malloc KeySetShapes");
    2630           0 :         size_t shapeCount = 0;
    2631             :         // shapefConstBinary
    2632           0 :         out[shapeCount].minWordLength = 1;
    2633           0 :         out[shapeCount].maxWordLength = 21;
    2634           0 :         out[shapeCount].special = 127;
    2635           0 :         out[shapeCount].parent = 0;
    2636           0 :         out[shapeCount].shapeInit = NULL;
    2637           0 :         out[shapeCount].shapef = shapefConstBinary;
    2638           0 :         out[shapeCount].shapeDel = NULL;
    2639           0 :         ++shapeCount;
    2640             : 
    2641             :         // shapefBinaryBranch
    2642           0 :         out[shapeCount].minWordLength = 1;
    2643           0 :         out[shapeCount].maxWordLength = 1;
    2644           0 :         out[shapeCount].special = 50;
    2645           0 :         out[shapeCount].parent = 7;
    2646           0 :         out[shapeCount].shapeInit = NULL;
    2647           0 :         out[shapeCount].shapef = shapefBinaryBranch;
    2648           0 :         out[shapeCount].shapeDel = NULL;
    2649           0 :         ++shapeCount;
    2650             : 
    2651             :         // shapefDynamicBranch
    2652           0 :         out[shapeCount].minWordLength = 1;
    2653           0 :         out[shapeCount].maxWordLength = 11;
    2654           0 :         out[shapeCount].special = 50;
    2655           0 :         out[shapeCount].parent = 7;
    2656           0 :         out[shapeCount].shapeInit = NULL;
    2657           0 :         out[shapeCount].shapef = shapefDynamicBranch;
    2658           0 :         out[shapeCount].shapeDel = NULL;
    2659           0 :         ++shapeCount;
    2660             : 
    2661             :         // shapefLateDynamicBranch
    2662           0 :         out[shapeCount].minWordLength = 1;
    2663           0 :         out[shapeCount].maxWordLength = 11;
    2664           0 :         out[shapeCount].special = 50;
    2665           0 :         out[shapeCount].parent = 7;
    2666           0 :         out[shapeCount].shapeInit = NULL;
    2667           0 :         out[shapeCount].shapef = shapefLateDynamicBranch;
    2668           0 :         out[shapeCount].shapeDel = NULL;
    2669           0 :         ++shapeCount;
    2670             : 
    2671             :         // shapefWide
    2672           0 :         out[shapeCount].minWordLength = 1;
    2673           0 :         out[shapeCount].maxWordLength = 11;
    2674           0 :         out[shapeCount].special = 50;
    2675           0 :         out[shapeCount].parent = 7;
    2676           0 :         out[shapeCount].shapeInit = NULL;
    2677           0 :         out[shapeCount].shapef = shapefWide;
    2678           0 :         out[shapeCount].shapeDel = NULL;
    2679           0 :         ++shapeCount;
    2680             : 
    2681             :         // shapefTight
    2682           0 :         out[shapeCount].minWordLength = 1;
    2683           0 :         out[shapeCount].maxWordLength = 11;
    2684           0 :         out[shapeCount].special = 50;
    2685           0 :         out[shapeCount].parent = 7;
    2686           0 :         out[shapeCount].shapeInit = NULL;
    2687           0 :         out[shapeCount].shapef = shapefTight;
    2688           0 :         out[shapeCount].shapeDel = NULL;
    2689           0 :         ++shapeCount;
    2690             : 
    2691             :         // shapefCommonStartEnd
    2692           0 :         out[shapeCount].minWordLength = 1;
    2693           0 :         out[shapeCount].maxWordLength = 21;
    2694           0 :         out[shapeCount].special = 50;
    2695           0 :         out[shapeCount].parent = 0;
    2696           0 :         out[shapeCount].shapeInit = shapeCommonStartEndInit;
    2697           0 :         out[shapeCount].shapef = shapefCommonStartEnd;
    2698           0 :         out[shapeCount].shapeDel = shapeCommonStartEndDel;
    2699           0 :         ++shapeCount;
    2700             : 
    2701             :         // shapefModules
    2702           0 :         out[shapeCount].minWordLength = 1;
    2703           0 :         out[shapeCount].maxWordLength = 11;
    2704           0 :         out[shapeCount].special = 50;
    2705           0 :         out[shapeCount].parent = 7;
    2706           0 :         out[shapeCount].shapeInit = shapeModulesInit;
    2707           0 :         out[shapeCount].shapef = shapefModules;
    2708           0 :         out[shapeCount].shapeDel = shapeModulesDel;
    2709           0 :         ++shapeCount;
    2710             : 
    2711             :         if (shapeCount != numberOfShapes) printExit ("shapeCount != numberOfShapes");
    2712           0 :         return out;
    2713             : }

Generated by: LCOV version 1.13