exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

perf_reserves_in_insert.c (7037B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file exchangedb/perf_reserves_in_insert.c
     18  * @brief benchmark for 'reserves_in_insert'
     19  * @author Joseph Xu
     20  */
     21 #include "taler/platform.h"
     22 #include "taler/taler_exchangedb_lib.h"
     23 #include "taler/taler_json_lib.h"
     24 #include "taler/taler_exchangedb_plugin.h"
     25 
     26 
     27 /**
     28  * Global result from the testcase.
     29  */
     30 static int result;
     31 
     32 /**
     33  * Report line of error if @a cond is true, and jump to label "drop".
     34  */
     35 #define FAILIF(cond)                            \
     36         do {                                          \
     37           if (! (cond)) {break;}                    \
     38           GNUNET_break (0);                           \
     39           goto drop;                                  \
     40         } while (0)
     41 
     42 
     43 /**
     44  * Initializes @a ptr with random data.
     45  */
     46 #define RND_BLK(ptr)                                                    \
     47         GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \
     48                                                                              ptr))
     49 
     50 /**
     51  * Initializes @a ptr with zeros.
     52  */
     53 #define ZR_BLK(ptr) \
     54         memset (ptr, 0, sizeof (*ptr))
     55 
     56 /**
     57  * How many rounds do we average over?
     58  */
     59 #define ROUNDS 5
     60 
     61 /**
     62  * Currency we use.  Must match test-exchange-db-*.conf.
     63  */
     64 #define CURRENCY "EUR"
     65 
     66 /**
     67  * Database plugin under test.
     68  */
     69 static struct TALER_EXCHANGEDB_Plugin *plugin;
     70 
     71 
     72 /**
     73  * Main function that will be run by the scheduler.
     74  *
     75  * @param cls closure with config
     76  */
     77 static void
     78 run (void *cls)
     79 {
     80   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
     81   const uint32_t num_partitions = 10;
     82   static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 32, 64, 128, 256, 512,
     83                                    1024, 1024, 512, 256, 128, 64, 32,
     84                                    16, 4, 3, 2, 1 };
     85   struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)];
     86   unsigned long long sqrs[sizeof (batches) / sizeof(*batches)];
     87 
     88   if (NULL ==
     89       (plugin = TALER_EXCHANGEDB_plugin_load (cfg,
     90                                               true)))
     91   {
     92     GNUNET_break (0);
     93     result = 77;
     94     return;
     95   }
     96   (void) plugin->drop_tables (plugin->cls);
     97   if (GNUNET_OK !=
     98       plugin->create_tables (plugin->cls,
     99                              true,
    100                              num_partitions))
    101   {
    102     GNUNET_break (0);
    103     result = 77;
    104     goto cleanup;
    105   }
    106 
    107   memset (times, 0, sizeof (times));
    108   memset (sqrs, 0, sizeof (sqrs));
    109   for (unsigned int r = 0; r < ROUNDS; r++)
    110   {
    111     for (unsigned int i = 0;
    112          i< sizeof(batches) / sizeof(*batches);
    113          i++)
    114     {
    115       unsigned int lcm = batches[i];
    116       struct TALER_Amount value;
    117       struct GNUNET_TIME_Absolute now;
    118       struct GNUNET_TIME_Timestamp ts;
    119       unsigned long long duration_sq;
    120       struct GNUNET_TIME_Relative duration;
    121 
    122       GNUNET_assert (GNUNET_OK ==
    123                      TALER_string_to_amount (CURRENCY ":1.000010",
    124                                              &value));
    125       now = GNUNET_TIME_absolute_get ();
    126       ts = GNUNET_TIME_timestamp_get ();
    127       {
    128         struct TALER_FullPayto sndr = {
    129           .full_payto = (char *) "payto://x-taler-bank/localhost:8080/1"
    130         };
    131         struct TALER_ReservePublicKeyP reserve_pubs[lcm];
    132         struct TALER_EXCHANGEDB_ReserveInInfo reserves[lcm];
    133         enum GNUNET_DB_QueryStatus results[lcm];
    134 
    135         for (unsigned int k = 0; k<lcm; k++)
    136         {
    137           RND_BLK (&reserve_pubs[k]);
    138           reserves[k].reserve_pub = &reserve_pubs[k];
    139           reserves[k].balance = &value;
    140           reserves[k].execution_time = ts;
    141           reserves[k].sender_account_details = sndr;
    142           reserves[k].exchange_account_name = "name";
    143           reserves[k].wire_reference = k;
    144         }
    145         FAILIF (lcm !=
    146                 plugin->reserves_in_insert (plugin->cls,
    147                                             reserves,
    148                                             lcm,
    149                                             results));
    150       }
    151       duration = GNUNET_TIME_absolute_get_duration (now);
    152       times[i] = GNUNET_TIME_relative_add (times[i],
    153                                            duration);
    154       duration_sq = duration.rel_value_us * duration.rel_value_us;
    155       GNUNET_assert (duration_sq / duration.rel_value_us ==
    156                      duration.rel_value_us);
    157       GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]);
    158       sqrs[i] += duration_sq;
    159     } /* for 'i' batch size */
    160   } /* for 'r' ROUNDS */
    161 
    162   for (unsigned int i = 0;
    163        i< sizeof(batches) / sizeof(*batches);
    164        i++)
    165   {
    166     unsigned int lcm = batches[i];
    167     struct GNUNET_TIME_Relative avg;
    168     double avg_dbl;
    169     double variance;
    170 
    171     avg = GNUNET_TIME_relative_divide (times[i],
    172                                        ROUNDS);
    173     avg_dbl = avg.rel_value_us;
    174     variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS);
    175     fprintf (stdout,
    176              "Batch[%4u]: %8llu us/entry ± %6.0f\n",
    177              batches[i],
    178              (unsigned long long) avg.rel_value_us / lcm,
    179              sqrt (variance / lcm / (ROUNDS - 1)));
    180   }
    181   result = 0;
    182 drop:
    183   GNUNET_break (GNUNET_OK ==
    184                 plugin->drop_tables (plugin->cls));
    185 cleanup:
    186   TALER_EXCHANGEDB_plugin_unload (plugin);
    187   plugin = NULL;
    188 }
    189 
    190 
    191 int
    192 main (int argc,
    193       char *const argv[])
    194 {
    195   const char *plugin_name;
    196   char *config_filename;
    197   char *testname;
    198   struct GNUNET_CONFIGURATION_Handle *cfg;
    199   (void) argc;
    200   result = -1;
    201   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    202   {
    203     GNUNET_break (0);
    204     return -1;
    205   }
    206 
    207   GNUNET_log_setup (argv[0],
    208                     "WARNING",
    209                     NULL);
    210   plugin_name++;
    211   (void) GNUNET_asprintf (&testname,
    212                           "test-exchange-db-%s",
    213                           plugin_name);
    214   (void) GNUNET_asprintf (&config_filename,
    215                           "%s.conf",
    216                           testname);
    217   cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
    218   if (GNUNET_OK !=
    219       GNUNET_CONFIGURATION_parse (cfg,
    220                                   config_filename))
    221   {
    222     GNUNET_break (0);
    223     GNUNET_free (config_filename);
    224     GNUNET_free (testname);
    225     return 2;
    226   }
    227   GNUNET_SCHEDULER_run (&run,
    228                         cfg);
    229   GNUNET_CONFIGURATION_destroy (cfg);
    230   GNUNET_free (config_filename);
    231   GNUNET_free (testname);
    232   return result;
    233 }
    234 
    235 
    236 /* end of perf_reserves_in_insert.c */