-simple DB benchmark

This commit is contained in:
Christian Grothoff 2021-11-29 00:17:09 +01:00
parent c3ce84af44
commit 65533e8df5
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 459 additions and 4 deletions

View File

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

View File

@ -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,

View File

@ -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;