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 */