diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-11-29 00:17:09 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-11-29 00:17:09 +0100 |
commit | 65533e8df5ea5ebf25bd9ae04186a475057efa9e (patch) | |
tree | 10bf4fc947d90c3a94d86e95defba35da199e082 | |
parent | c3ce84af44d7c281eb402500510053e2af86c314 (diff) |
-simple DB benchmark
-rw-r--r-- | src/exchangedb/bench-db-postgres.conf | 4 | ||||
-rw-r--r-- | src/exchangedb/bench_db.c | 429 | ||||
-rw-r--r-- | src/exchangedb/benchmark-0001.sql | 30 |
3 files changed, 459 insertions, 4 deletions
diff --git a/src/exchangedb/bench-db-postgres.conf b/src/exchangedb/bench-db-postgres.conf index a573e6b95..837ae41e2 100644 --- a/src/exchangedb/bench-db-postgres.conf +++ b/src/exchangedb/bench-db-postgres.conf @@ -4,3 +4,7 @@ # [bench-db-postgres] CONFIG = postgres:///talercheck + +# Where are the SQL files to setup our tables? +# Important: this MUST end with a "/"! +SQL_DIR = $DATADIR/sql/exchange/ diff --git a/src/exchangedb/bench_db.c b/src/exchangedb/bench_db.c index 299b852d0..1e95df279 100644 --- a/src/exchangedb/bench_db.c +++ b/src/exchangedb/bench_db.c @@ -22,6 +22,12 @@ */ #include "platform.h" #include <gnunet/gnunet_pq_lib.h> +#include "taler_util.h" + +/** + * How many elements should we insert? + */ +#define TOTAL (1024 * 16) /** * Global result from the testcase. @@ -35,6 +41,261 @@ static int result; GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) +static bool +prepare (struct GNUNET_PQ_Context *conn) +{ + struct GNUNET_PQ_PreparedStatement ps[] = { + GNUNET_PQ_make_prepare ( + "bm_insert", + "INSERT INTO benchmap " + "(hc" + ",expiration_date" + ") VALUES " + "($1, $2);", + 2), + /* Used in #postgres_iterate_denomination_info() */ + GNUNET_PQ_make_prepare ( + "bm_select", + "SELECT" + " expiration_date" + " FROM benchmap" + " WHERE hc=$1;", + 1), + GNUNET_PQ_make_prepare ( + "bhm_insert", + "INSERT INTO benchhmap " + "(hc" + ",expiration_date" + ") VALUES " + "($1, $2);", + 2), + /* Used in #postgres_iterate_denomination_info() */ + GNUNET_PQ_make_prepare ( + "bhm_select", + "SELECT" + " expiration_date" + " FROM benchhmap" + " WHERE hc=$1;", + 1), + GNUNET_PQ_make_prepare ( + "bem_insert", + "INSERT INTO benchemap " + "(hc" + ",ihc" + ",expiration_date" + ") VALUES " + "($1, $2, $3);", + 3), + /* Used in #postgres_iterate_denomination_info() */ + GNUNET_PQ_make_prepare ( + "bem_select", + "SELECT" + " expiration_date" + " FROM benchemap" + " WHERE ihc=$1 AND hc=$2;", + 2), + GNUNET_PQ_PREPARED_STATEMENT_END + }; + enum GNUNET_GenericReturnValue ret; + + ret = GNUNET_PQ_prepare_statements (conn, + ps); + if (GNUNET_OK != ret) + return false; + return true; +} + + +static bool +bm_insert (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + + now = GNUNET_TIME_absolute_get (); + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_non_select (conn, + "bm_insert", + params); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + +static bool +bhm_insert (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + + now = GNUNET_TIME_absolute_get (); + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_non_select (conn, + "bhm_insert", + params); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + +static bool +bem_insert (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + uint32_t ihc; + + now = GNUNET_TIME_absolute_get (); + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + memcpy (&ihc, + &hc, + sizeof (ihc)); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_uint32 (&ihc), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_non_select (conn, + "bem_insert", + params); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + +static bool +bm_select (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_absolute_time ("expiration_date", + &now), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select (conn, + "bm_select", + params, + rs); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + +static bool +bhm_select (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_absolute_time ("expiration_date", + &now), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select (conn, + "bhm_select", + params, + rs); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + +static bool +bem_select (struct GNUNET_PQ_Context *conn, + unsigned int i) +{ + uint32_t b = htonl ((uint32_t) i); + struct GNUNET_HashCode hc; + struct GNUNET_TIME_Absolute now; + uint32_t ihc; + + GNUNET_CRYPTO_hash (&b, + sizeof (b), + &hc); + memcpy (&ihc, + &hc, + sizeof (ihc)); + { + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint32 (&ihc), + GNUNET_PQ_query_param_auto_from_type (&hc), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_absolute_time ("expiration_date", + &now), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + qs = GNUNET_PQ_eval_prepared_singleton_select (conn, + "bem_select", + params, + rs); + return (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); + } +} + + /** * Main function that will be run by the scheduler. * @@ -45,6 +306,10 @@ run (void *cls) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_PQ_Context *conn; + struct GNUNET_PQ_Context *conn2; + struct GNUNET_TIME_Absolute now; + pid_t f; + int status; conn = GNUNET_PQ_connect_with_cfg (cfg, "bench-db-postgres", @@ -57,6 +322,167 @@ run (void *cls) GNUNET_break (0); return; } + conn2 = GNUNET_PQ_connect_with_cfg (cfg, + "bench-db-postgres", + NULL, + NULL, + NULL); + if (! prepare (conn)) + { + GNUNET_PQ_disconnect (conn); + GNUNET_PQ_disconnect (conn2); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + if (! prepare (conn2)) + { + GNUNET_PQ_disconnect (conn); + GNUNET_PQ_disconnect (conn2); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + { + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_try_execute ("DELETE FROM benchmap;"), + GNUNET_PQ_make_try_execute ("DELETE FROM benchemap;"), + GNUNET_PQ_make_try_execute ("DELETE FROM benchhmap;"), + GNUNET_PQ_EXECUTE_STATEMENT_END + }; + + GNUNET_assert (GNUNET_OK == + GNUNET_PQ_exec_statements (conn, + es)); + } + now = GNUNET_TIME_absolute_get (); + for (unsigned int i = 0; i<TOTAL; i++) + if (! bm_insert (conn, + i)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Insertion of %u elements took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); + now = GNUNET_TIME_absolute_get (); + f = fork (); + for (unsigned int i = 0; i<TOTAL; i++) + { + uint32_t j; + + j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + TOTAL); + if (! bm_select ((0 == f)? conn2 : conn, + j)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + } + if (0 == f) + exit (0); + waitpid (f, &status, 0); + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Selection of 2x%u elements took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); + + now = GNUNET_TIME_absolute_get (); + for (unsigned int i = 0; i<TOTAL; i++) + if (! bhm_insert (conn, + i)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Insertion of %u elements with hash index took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); + now = GNUNET_TIME_absolute_get (); + f = fork (); + for (unsigned int i = 0; i<TOTAL; i++) + { + uint32_t j; + + j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + TOTAL); + if (! bhm_select ((0 == f)? conn2 : conn, + j)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + } + if (0 == f) + exit (0); + waitpid (f, &status, 0); + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Selection of 2x%u elements with hash index took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); + + now = GNUNET_TIME_absolute_get (); + for (unsigned int i = 0; i<TOTAL; i++) + if (! bem_insert (conn, + i)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Insertion of %u elements with short element took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); + now = GNUNET_TIME_absolute_get (); + f = fork (); + for (unsigned int i = 0; i<TOTAL; i++) + { + uint32_t j; + + j = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, + TOTAL); + if (! bem_select ((0 == f)? conn2 : conn, + j)) + { + GNUNET_PQ_disconnect (conn); + result = EXIT_FAILURE; + GNUNET_break (0); + return; + } + } + if (0 == f) + exit (0); + waitpid (f, &status, 0); + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Selection of 2x%u elements with short element took %s\n", + (unsigned int) TOTAL, + GNUNET_STRINGS_relative_time_to_string ( + GNUNET_TIME_absolute_get_duration (now), + GNUNET_YES)); GNUNET_PQ_disconnect (conn); } @@ -79,7 +505,7 @@ main (int argc, return -1; } GNUNET_log_setup (argv[0], - "WARNING", + "INFO", NULL); plugin_name++; (void) GNUNET_asprintf (&testname, @@ -88,6 +514,7 @@ main (int argc, (void) GNUNET_asprintf (&config_filename, "%s.conf", testname); + TALER_OS_init (); cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, diff --git a/src/exchangedb/benchmark-0001.sql b/src/exchangedb/benchmark-0001.sql index 07fe49407..34fed6a55 100644 --- a/src/exchangedb/benchmark-0001.sql +++ b/src/exchangedb/benchmark-0001.sql @@ -20,12 +20,36 @@ BEGIN; -- Check patch versioning is in place. SELECT _v.register_patch('benchmark-0001', NULL, NULL); - +-- Naive, btree version CREATE TABLE IF NOT EXISTS benchmap - (reserve_uuid BIGSERIAL UNIQUE - ,hash BYTEA PRIMARY KEY CHECK(LENGTH(hash)=64) + (uuid BIGSERIAL PRIMARY KEY + ,hc BYTEA UNIQUE CHECK(LENGTH(hc)=64) + ,expiration_date INT8 NOT NULL + ); + +-- Replace btree with hash-based index +CREATE TABLE IF NOT EXISTS benchhmap + (uuid BIGSERIAL PRIMARY KEY + ,hc BYTEA NOT NULL CHECK(LENGTH(hc)=64) + ,expiration_date INT8 NOT NULL + ); +CREATE INDEX IF NOT EXISTS benchhmap_index + ON benchhmap + USING HASH (hc); +ALTER TABLE benchhmap + ADD CONSTRAINT pk + EXCLUDE USING HASH (hc with =); + +-- Keep btree, also add 32-bit hash-based index on top +CREATE TABLE IF NOT EXISTS benchemap + (uuid BIGSERIAL PRIMARY KEY + ,ihc INT4 NOT NULL + ,hc BYTEA UNIQUE CHECK(LENGTH(hc)=64) ,expiration_date INT8 NOT NULL ); +CREATE INDEX IF NOT EXISTS benchemap_index + ON benchemap + USING HASH (ihc); -- Complete transaction COMMIT; |