30 #if defined(WIN32) && FD_SETSIZE < 1024
31 #error FD_SETSIZE needs to have been increased
46 #if defined(HAVE_PPOLL) && !defined(PGBENCH_USE_SELECT)
47 #define POLL_USING_PPOLL
52 #define POLL_USING_SELECT
73 #define M_PI 3.14159265358979323846
76 #define ERRCODE_T_R_SERIALIZATION_FAILURE "40001"
77 #define ERRCODE_T_R_DEADLOCK_DETECTED "40P01"
78 #define ERRCODE_UNDEFINED_TABLE "42P01"
83 #define FNV_PRIME UINT64CONST(0x100000001b3)
84 #define FNV_OFFSET_BASIS UINT64CONST(0xcbf29ce484222325)
85 #define MM2_MUL UINT64CONST(0xc6a4a7935bd1e995)
86 #define MM2_MUL_TIMES_8 UINT64CONST(0x35253c9ade8f4ca8)
93 #ifdef POLL_USING_PPOLL
94 #define SOCKET_WAIT_METHOD "ppoll"
105 #ifdef POLL_USING_SELECT
106 #define SOCKET_WAIT_METHOD "select"
123 #define GETERRNO() (_dosmaperr(GetLastError()), errno)
124 #define THREAD_T HANDLE
125 #define THREAD_FUNC_RETURN_TYPE unsigned
126 #define THREAD_FUNC_RETURN return 0
127 #define THREAD_FUNC_CC __stdcall
128 #define THREAD_CREATE(handle, function, arg) \
129 ((*(handle) = (HANDLE) _beginthreadex(NULL, 0, (function), (arg), 0, NULL)) == 0 ? errno : 0)
130 #define THREAD_JOIN(handle) \
131 (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 ? \
132 GETERRNO() : CloseHandle(handle) ? 0 : GETERRNO())
133 #define THREAD_BARRIER_T SYNCHRONIZATION_BARRIER
134 #define THREAD_BARRIER_INIT(barrier, n) \
135 (InitializeSynchronizationBarrier((barrier), (n), 0) ? 0 : GETERRNO())
136 #define THREAD_BARRIER_WAIT(barrier) \
137 EnterSynchronizationBarrier((barrier), \
138 SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
139 #define THREAD_BARRIER_DESTROY(barrier)
143 #define THREAD_T pthread_t
144 #define THREAD_FUNC_RETURN_TYPE void *
145 #define THREAD_FUNC_RETURN return NULL
146 #define THREAD_FUNC_CC
147 #define THREAD_CREATE(handle, function, arg) \
148 pthread_create((handle), NULL, (function), (arg))
149 #define THREAD_JOIN(handle) \
150 pthread_join((handle), NULL)
151 #define THREAD_BARRIER_T pthread_barrier_t
152 #define THREAD_BARRIER_INIT(barrier, n) \
153 pthread_barrier_init((barrier), NULL, (n))
154 #define THREAD_BARRIER_WAIT(barrier) pthread_barrier_wait((barrier))
155 #define THREAD_BARRIER_DESTROY(barrier) pthread_barrier_destroy((barrier))
162 #define DEFAULT_INIT_STEPS "dtgvp"
163 #define ALL_INIT_STEPS "dtgGvpf"
165 #define LOG_STEP_SECONDS 5
166 #define DEFAULT_NXACTS 10
168 #define MIN_GAUSSIAN_PARAM 2.0
170 #define MIN_ZIPFIAN_PARAM 1.001
171 #define MAX_ZIPFIAN_PARAM 1000.0
246 #define naccounts 100000
255 #define SCALE_32BIT_THRESHOLD 20000
311 #define VARIABLES_ALLOC_MARGIN 8
348 #define MAX_SCRIPTS 128
349 #define SHELL_COMMAND_SIZE 256
662 int64 throttle_trigger;
679 #define SQL_COMMAND 1
680 #define META_COMMAND 2
715 static const char *
const QUERYMODE[] = {
"simple",
"extended",
"prepared"};
785 "<builtin: TPC-B (sort of)>",
789 "\\set delta random(-5000, 5000)\n"
791 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
792 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
793 "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
794 "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
795 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
800 "<builtin: simple update>",
804 "\\set delta random(-5000, 5000)\n"
806 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
807 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
808 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
813 "<builtin: select only>",
815 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
829 StatsData *agg,
bool skipped,
double latency,
double lag);
868 #define PG_TIME_GET_DOUBLE(t) (0.000001 * (t))
873 printf(
"%s is a benchmarking tool for PostgreSQL.\n\n"
875 " %s [OPTION]... [DBNAME]\n"
876 "\nInitialization options:\n"
877 " -i, --initialize invokes initialization mode\n"
879 " run selected initialization steps, in the specified order\n"
880 " d: drop any existing pgbench tables\n"
881 " t: create the tables used by the standard pgbench scenario\n"
882 " g: generate data, client-side\n"
883 " G: generate data, server-side\n"
884 " v: invoke VACUUM on the standard tables\n"
885 " p: create primary key indexes on the standard tables\n"
886 " f: create foreign keys between the standard tables\n"
887 " -F, --fillfactor=NUM set fill factor\n"
888 " -n, --no-vacuum do not run VACUUM during initialization\n"
889 " -q, --quiet quiet logging (one message each 5 seconds)\n"
890 " -s, --scale=NUM scaling factor\n"
891 " --foreign-keys create foreign key constraints between tables\n"
892 " --index-tablespace=TABLESPACE\n"
893 " create indexes in the specified tablespace\n"
894 " --partition-method=(range|hash)\n"
895 " partition pgbench_accounts with this method (default: range)\n"
896 " --partitions=NUM partition pgbench_accounts into NUM parts (default: 0)\n"
897 " --tablespace=TABLESPACE create tables in the specified tablespace\n"
898 " --unlogged-tables create tables as unlogged tables\n"
899 "\nOptions to select what to run:\n"
900 " -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
901 " (use \"-b list\" to list available scripts)\n"
902 " -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
903 " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
904 " (same as \"-b simple-update\")\n"
905 " -S, --select-only perform SELECT-only transactions\n"
906 " (same as \"-b select-only\")\n"
907 "\nBenchmarking options:\n"
908 " -c, --client=NUM number of concurrent database clients (default: 1)\n"
909 " -C, --connect establish new connection for each transaction\n"
910 " -D, --define=VARNAME=VALUE\n"
911 " define variable for use by custom script\n"
912 " -j, --jobs=NUM number of threads (default: 1)\n"
913 " -l, --log write transaction times to log file\n"
914 " -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
915 " -M, --protocol=simple|extended|prepared\n"
916 " protocol for submitting queries (default: simple)\n"
917 " -n, --no-vacuum do not run VACUUM before tests\n"
918 " -P, --progress=NUM show thread progress report every NUM seconds\n"
919 " -r, --report-per-command report latencies, failures, and retries per command\n"
920 " -R, --rate=NUM target rate in transactions per second\n"
921 " -s, --scale=NUM report this scale factor in output\n"
922 " -t, --transactions=NUM number of transactions each client runs (default: 10)\n"
923 " -T, --time=NUM duration of benchmark test in seconds\n"
924 " -v, --vacuum-all vacuum all four standard tables before tests\n"
925 " --aggregate-interval=NUM aggregate data over NUM seconds\n"
926 " --exit-on-abort exit when any client is aborted\n"
927 " --failures-detailed report the failures grouped by basic types\n"
928 " --log-prefix=PREFIX prefix for transaction time log file\n"
929 " (default: \"pgbench_log\")\n"
930 " --max-tries=NUM max number of tries to run transaction (default: 1)\n"
931 " --progress-timestamp use Unix epoch timestamps for progress\n"
932 " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
933 " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
934 " --show-script=NAME show builtin script code, then exit\n"
935 " --verbose-errors print messages of all errors\n"
936 "\nCommon options:\n"
937 " --debug print debugging output\n"
938 " -d, --dbname=DBNAME database name to connect to\n"
939 " -h, --host=HOSTNAME database server host or socket directory\n"
940 " -p, --port=PORT database server port number\n"
941 " -U, --username=USERNAME connect as specified database user\n"
942 " -V, --version output version information, then exit\n"
943 " -?, --help show this help, then exit\n"
945 "Report bugs to <%s>.\n"
946 "%s home page: <%s>\n",
954 const char *ptr =
str;
957 while (*ptr && isspace((
unsigned char) *ptr))
961 if (*ptr ==
'+' || *ptr ==
'-')
965 if (*ptr && !isdigit((
unsigned char) *ptr))
969 while (*ptr && isdigit((
unsigned char) *ptr))
991 const char *ptr =
str;
1004 while (*ptr && isspace((
unsigned char) *ptr))
1013 else if (*ptr ==
'+')
1017 if (
unlikely(!isdigit((
unsigned char) *ptr)))
1018 goto invalid_syntax;
1021 while (*ptr && isdigit((
unsigned char) *ptr))
1023 int8 digit = (*ptr++ -
'0');
1031 while (*ptr !=
'\0' && isspace((
unsigned char) *ptr))
1035 goto invalid_syntax;
1065 *dv = strtod(
str, &end);
1123 cut = exp(-parameter);
1130 Assert((1.0 - cut) != 0.0);
1131 rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1133 return min + (int64) ((max - min + 1) * rand);
1163 while (stdev < -parameter || stdev >= parameter);
1166 rand = (stdev + parameter) / (parameter * 2.0);
1169 return min + (int64) ((max - min + 1) * rand);
1191 return (int64) (-log(uniform) * center + 0.5);
1204 double b = pow(2.0, s - 1.0);
1220 x = floor(pow(u, -1.0 / (s - 1.0)));
1222 t = pow(1.0 + 1.0 /
x, s - 1.0);
1224 if (v *
x * (t - 1.0) / (
b - 1.0) <= t /
b &&
x <= n)
1234 int64 n = max - min + 1;
1252 for (
i = 0;
i < 8; ++
i)
1257 result = result ^ octet;
1274 uint64 k = (uint64)
val;
1287 return (int64) result;
1304 permute(
const int64
val,
const int64 isize,
const int64 seed)
1321 size = (uint64) isize;
1326 mask = (((uint64) 1) << masklen) - 1;
1357 for (
i = 0;
i < 6;
i++)
1368 v = ((v * m) ^ r) & mask;
1369 v = ((v << 1) & mask) | (v >> (masklen - 1));
1378 t = ((t * m) ^ r) & mask;
1379 t = ((t << 1) & mask) | (t >> (masklen - 1));
1406 if (ss->
count == 0 || val < ss->min)
1469 stats->
retries += (tries - 1);
1495 pg_fatal(
"unexpected error status: %d", estatus);
1544 #define PARAMS_ARRAY_SIZE 7
1549 keywords[0] =
"host";
1551 keywords[1] =
"port";
1553 keywords[2] =
"user";
1555 keywords[3] =
"password";
1557 keywords[4] =
"dbname";
1559 keywords[5] =
"fallback_application_name";
1610 if (variables->
nvars <= 0)
1635 char stringform[64];
1647 snprintf(stringform,
sizeof(stringform),
"NULL");
1649 snprintf(stringform,
sizeof(stringform),
1652 snprintf(stringform,
sizeof(stringform),
1655 snprintf(stringform,
sizeof(stringform),
1672 slen = strlen(var->
svalue);
1716 pg_log_error(
"malformed variable \"%s\" value: \"%s\"",
1741 const unsigned char *ptr = (
const unsigned char *)
name;
1749 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1759 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1760 "_0123456789", *ptr) != NULL)
1777 needed += variables->
nvars;
1813 var = &(variables->
vars[variables->
nvars]);
1897 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1898 "_", sql[
i]) != NULL)
1904 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1905 "_0123456789", sql[
i]) != NULL)
1909 memcpy(
name, &sql[1],
i - 1);
1919 int valueln = strlen(
value);
1923 size_t offset = param - *sql;
1926 param = *sql + offset;
1930 memmove(param + valueln, param +
len, strlen(param +
len) + 1);
1931 memcpy(param,
value, valueln);
1933 return param + valueln;
1944 while ((p = strchr(p,
':')) != NULL)
1974 const char **params)
1978 for (
i = 0;
i < command->
argc - 1;
i++)
2009 *bval = pval->
u.
bval;
2032 return pval->
u.
bval;
2034 return pval->
u.
ival != 0;
2036 return pval->
u.
dval != 0.0;
2050 *ival = pval->
u.
ival;
2055 double dval = rint(pval->
u.
dval);
2062 *ival = (int64) dval;
2078 *dval = pval->
u.
dval;
2083 *dval = (double) pval->
u.
ival;
2228 if (
args->next == NULL)
2243 #define MAX_FARGS 16
2257 bool has_null =
false;
2265 for (nargs = 0; nargs <
MAX_FARGS && l != NULL; nargs++, l = l->
next)
2513 double d = varg->
u.
dval;
2528 fprintf(stderr,
"debug(script=%d,command=%d): ",
2534 fprintf(stderr,
"boolean %s\n", varg->
u.
bval ?
"true" :
"false");
2538 fprintf(stderr,
"double %.*g\n", DBL_DIG, varg->
u.
dval);
2597 for (
i = 0;
i < nargs;
i++)
2611 for (
i = 1;
i < nargs;
i++)
2618 extremum =
Min(extremum, dval);
2620 extremum =
Max(extremum, dval);
2630 for (
i = 1;
i < nargs;
i++)
2637 extremum =
Min(extremum, ival);
2639 extremum =
Max(extremum, ival);
2694 pg_log_error(
"gaussian parameter must be at least %f (not %f)",
2701 imin, imax, param));
2707 pg_log_error(
"zipfian parameter must be in range [%.3f, %.0f] (not %f)",
2719 pg_log_error(
"exponential parameter must be greater than zero (not %f)",
2726 imin, imax, param));
2804 pg_log_error(
"permute size parameter must be greater than zero");
2840 switch (expr->
etype)
2861 *retval = var->
value;
2873 pg_fatal(
"unexpected enode type in evaluation: %d", expr->
etype);
2941 for (
i = 0;
i < argc;
i++)
2946 if (argv[
i][0] !=
':')
2950 else if (argv[
i][1] ==
':')
2956 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[
i]);
2960 arglen = strlen(
arg);
2963 pg_log_error(
"%s: shell command is too long", argv[0]);
2968 command[
len++] =
' ';
2969 memcpy(command +
len,
arg, arglen);
2973 command[
len] =
'\0';
2980 if (system(command))
2983 pg_log_error(
"%s: could not launch shell command", argv[0]);
2990 if ((fp = popen(command,
"r")) == NULL)
2992 pg_log_error(
"%s: could not launch shell command", argv[0]);
2995 if (fgets(
res,
sizeof(
res), fp) == NULL)
2998 pg_log_error(
"%s: could not read result of shell command", argv[0]);
3004 pg_log_error(
"%s: could not run shell command: %m", argv[0]);
3009 retval = (int) strtol(
res, &endptr, 10);
3010 while (*endptr !=
'\0' && isspace((
unsigned char) *endptr))
3012 if (*
res ==
'\0' || *endptr !=
'\0')
3014 pg_log_error(
"%s: shell command must return an integer (not \"%s\")", argv[0],
res);
3020 pg_log_debug(
"%s: shell parameter name: \"%s\", value: \"%s\"", argv[0], argv[1],
res);
3031 pg_log_error(
"client %d aborted in command %d (%s) of script %d; %s",
3042 pg_log_info(
"client %d got an error in command %d (SQL) of script %d; %s",
3080 for (numcmds = 0; script->
commands[numcmds] != NULL; numcmds++)
3107 command->
argv[0], command->
argc - 1, NULL);
3142 for (
j = st->
command + 1; commands[
j] != NULL;
j++)
3173 const char *sql = command->
argv[0];
3180 NULL, params, NULL, NULL, 0);
3191 params, NULL, NULL, 0);
3211 if (sqlState != NULL)
3264 is_last = (next_res == NULL);
3272 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3287 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3292 else if (meta ==
META_ASET && ntuples <= 0)
3304 if (*varprefix !=
'\0')
3305 varname =
psprintf(
"%s%s", varprefix, varname);
3312 pg_log_error(
"client %d script %d command %d query %d: error storing into variable %s",
3318 if (*varprefix !=
'\0')
3326 pg_log_debug(
"client %d pipeline ending, ongoing syncs: %d",
3330 pg_log_error(
"client %d failed to exit pipeline mode: %s", st->
id,
3348 pg_log_error(
"client %d script %d aborted in command %d query %d: %s",
3389 if (*argv[1] ==
':')
3391 if ((var =
getVariable(variables, argv[1] + 1)) == NULL)
3393 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3400 if (usec == 0 && !isdigit((
unsigned char) *var))
3402 pg_log_error(
"%s: invalid sleep time \"%s\" for variable \"%s\"",
3403 argv[0], var, argv[1] + 1);
3408 usec = atoi(argv[1]);
3480 pg_log_error(
"client %d aborted: failed to send a pipeline sync",
3503 pg_log_error(
"client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3539 pg_log_error(
"unexpected transaction status %d", tx_status);
3563 "repeats the transaction after the error" :
3564 "ends the failed transaction"));
3643 if (st->
con == NULL)
3653 pg_log_error(
"client %d aborted while establishing connection", st->
id);
3761 if (now < st->txn_scheduled)
3778 if (command == NULL)
3784 pg_log_error(
"client %d aborted: end of script reached with pipeline open",
3807 commandFailed(st,
"gset",
"\\gset is not allowed in pipeline mode");
3813 commandFailed(st,
"aset",
"\\aset is not allowed in pipeline mode");
3967 commandFailed(st,
"SQL",
"perhaps the backend died while processing");
4001 if (now < st->sleep_until)
4065 pg_log_error(
"client %d aborted: failed to send sql command for rolling back the failed transaction",
4084 pg_log_error(
"perhaps the backend died while processing");
4086 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4102 pg_log_error(
"client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4131 pg_log_error(
"client %d aborted while rolling back the transaction after an error; %s",
4211 pg_log_error(
"client %d aborted: end of script reached without completing the last transaction",
4219 pg_log_error(
"perhaps the backend died while processing");
4221 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4294 argc = command->
argc;
4295 argv = command->
argv;
4304 for (
int i = 1;
i < argc;
i++)
4324 commandFailed(st,
"sleep",
"execution of meta-command failed");
4339 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4345 commandFailed(st,
"set",
"assignment of meta-command failed");
4358 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4381 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4415 commandFailed(st,
"setshell",
"execution of meta-command failed");
4423 commandFailed(st,
"shell",
"execution of meta-command failed");
4435 commandFailed(st,
"startpipeline",
"cannot use pipeline mode with the simple query protocol");
4451 commandFailed(st,
"startpipeline",
"already in pipeline mode");
4456 commandFailed(st,
"startpipeline",
"failed to enter pipeline mode");
4469 commandFailed(st,
"syncpipeline",
"failed to send a pipeline sync");
4483 commandFailed(st,
"endpipeline",
"failed to send a pipeline sync");
4525 return "serialization";
4530 pg_fatal(
"unexpected error status: %d", estatus);
4548 StatsData *agg,
bool skipped,
double latency,
double lag)
4576 double lag_sum = 0.0;
4577 double lag_sum2 = 0.0;
4578 double lag_min = 0.0;
4579 double lag_max = 0.0;
4581 int64 serialization_failures = 0;
4582 int64 deadlock_failures = 0;
4625 serialization_failures,
4644 now / 1000000,
now % 1000000);
4670 double latency = 0.0,
4695 doLog(thread, st, agg, skipped, latency, lag);
4710 for (
i = 0;
i < length;
i++)
4720 fprintf(stderr,
"dropping old tables...\n");
4727 "pgbench_accounts, "
4728 "pgbench_branches, "
4758 "create%s table pgbench_accounts_%d\n"
4759 " partition of pgbench_accounts\n"
4760 " for values from (",
4785 "create%s table pgbench_accounts_%d\n"
4786 " partition of pgbench_accounts\n"
4787 " for values with (modulus %d, remainder %d)",
4826 const char *bigcols;
4827 int declare_fillfactor;
4829 static const struct ddlinfo DDLs[] = {
4832 "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4833 "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4838 "tid int not null,bid int,tbalance int,filler char(84)",
4839 "tid int not null,bid int,tbalance int,filler char(84)",
4844 "aid int not null,bid int,abalance int,filler char(84)",
4845 "aid bigint not null,bid int,abalance int,filler char(84)",
4850 "bid int not null,bbalance int,filler char(88)",
4851 "bid int not null,bbalance int,filler char(88)",
4858 fprintf(stderr,
"creating tables...\n");
4864 const struct ddlinfo *ddl = &DDLs[
i];
4876 else if (ddl->declare_fillfactor)
4884 char *escape_tablespace;
4907 "pgbench_accounts, "
4908 "pgbench_branches, "
4949 char copy_statement[256];
4950 const char *copy_statement_fmt =
"copy %s from stdin";
4951 int64 total = base *
scale;
4955 int log_interval = 1;
4958 char eol = isatty(fileno(stderr)) ?
'\r' :
'\n';
4968 if (strcmp(table,
"pgbench_accounts") != 0 ||
4970 copy_statement_fmt =
"copy %s from stdin with (freeze on)";
4973 n =
pg_snprintf(copy_statement,
sizeof(copy_statement), copy_statement_fmt, table);
4974 if (n >=
sizeof(copy_statement))
4975 pg_fatal(
"invalid buffer size: must be at least %d characters long", n);
4987 for (k = 0; k < total; k++)
5005 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5009 (
int) ((
j * 100) / total),
5010 table, elapsed_sec, remaining_sec, eol);
5016 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5023 (
int) ((
j * 100) / total),
5024 table, elapsed_sec, remaining_sec, eol);
5032 if (
chars != 0 && eol !=
'\n')
5036 pg_fatal(
"very last PQputline failed");
5052 fprintf(stderr,
"generating data (client-side)...\n");
5086 fprintf(stderr,
"generating data (server-side)...\n");
5100 "insert into pgbench_branches(bid,bbalance) "
5106 "insert into pgbench_tellers(tid,bid,tbalance) "
5107 "select tid, (tid - 1) / %d + 1, 0 "
5112 "insert into pgbench_accounts(aid,bid,abalance,filler) "
5113 "select aid, (aid - 1) / %d + 1, 0, '' "
5129 fprintf(stderr,
"vacuuming...\n");
5142 static const char *
const DDLINDEXes[] = {
5143 "alter table pgbench_branches add primary key (bid)",
5144 "alter table pgbench_tellers add primary key (tid)",
5145 "alter table pgbench_accounts add primary key (aid)"
5150 fprintf(stderr,
"creating primary keys...\n");
5160 char *escape_tablespace;
5180 static const char *
const DDLKEYs[] = {
5181 "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5182 "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5183 "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5184 "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5185 "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5189 fprintf(stderr,
"creating foreign keys...\n");
5206 if (initialize_steps[0] ==
'\0')
5207 pg_fatal(
"no initialization steps specified");
5209 for (
const char *step = initialize_steps; *step !=
'\0'; step++)
5213 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5229 double run_time = 0.0;
5235 pg_fatal(
"could not create connection for initialization");
5240 for (step = initialize_steps; *step !=
'\0'; step++)
5252 op =
"create tables";
5256 op =
"client-side generate";
5260 op =
"server-side generate";
5268 op =
"primary keys";
5272 op =
"foreign keys";
5278 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5294 run_time += elapsed_sec;
5298 fprintf(stderr,
"done in %.2f s (%s).\n", run_time, stats.
data);
5317 res =
PQexec(con,
"select count(*) from pgbench_branches");
5325 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5332 pg_fatal(
"invalid count(*) from pgbench_branches: \"%s\"",
5338 pg_log_warning(
"scale option ignored, using count from pgbench_branches table (%d)",
5357 "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5358 "from pg_catalog.pg_class as c "
5359 "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5360 "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5361 "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5362 "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5363 "where c.relname = 'pgbench_accounts' and o.n is not null "
5380 pg_log_error(
"no pgbench_accounts table found in \"search_path\"");
5381 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
PQdb(con));
5396 if (strcmp(
ps,
"r") == 0)
5398 else if (strcmp(
ps,
"h") == 0)
5403 pg_fatal(
"unexpected partition method: \"%s\"",
ps);
5426 while ((p = strchr(p,
':')) != NULL)
5448 pg_log_error(
"statement has too many arguments (maximum is %d): %s",
5480 const char *line,
const char *command,
5481 const char *msg,
const char *more,
int column)
5490 if (column >= 0 && line == NULL)
5492 if (command != NULL)
5501 fprintf(stderr,
"%s\n", line);
5503 fprintf(stderr,
"%*c error found here\n", column + 1,
'^');
5517 char *p = sql_command;
5522 if (isspace((
unsigned char) *p))
5524 else if (strncmp(p,
"--", 2) == 0)
5526 p = strchr(p,
'\n');
5565 my_command->
argc = 0;
5568 memset(my_command->
argv, 0,
sizeof(my_command->
argv));
5570 my_command->
expr = NULL;
5583 for (
int i = 0;
i < command->
argc;
i++)
5602 static int prepnum = 0;
5608 buffer[strcspn(buffer,
"\n\r")] =
'\0';
5662 my_command->
argc = 0;
5667 offsets[
j] = word_offset;
5685 "missing argument", NULL, -1);
5687 offsets[
j] = word_offset;
5694 my_command->
argv[0]);
5727 "too many arguments", NULL, -1);
5729 offsets[
j] = word_offset;
5743 if (my_command->
argc < 2)
5745 "missing argument", NULL, -1);
5747 if (my_command->
argc > 3)
5749 "too many arguments", NULL,
5750 offsets[3] - start_offset);
5758 if (my_command->
argv[1][0] !=
':')
5760 char *
c = my_command->
argv[1];
5761 bool have_digit =
false;
5764 if (*
c ==
'+' || *
c ==
'-')
5768 if (*
c && isdigit((
unsigned char) *
c))
5772 while (*
c && isdigit((
unsigned char) *
c))
5777 if (my_command->
argc == 2 && have_digit)
5779 my_command->
argv[2] =
c;
5780 offsets[2] = offsets[1] + (
c - my_command->
argv[1]);
5781 my_command->
argc = 3;
5790 "invalid sleep time, must be an integer",
5791 my_command->
argv[1], offsets[1] - start_offset);
5796 if (my_command->
argc == 3)
5802 "unrecognized time unit, must be us, ms or s",
5803 my_command->
argv[2], offsets[2] - start_offset);
5808 if (my_command->
argc < 3)
5810 "missing argument", NULL, -1);
5814 if (my_command->
argc < 2)
5816 "missing command", NULL, -1);
5823 if (my_command->
argc != 1)
5825 "unexpected argument", NULL, -1);
5829 if (my_command->
argc > 2)
5831 "too many arguments", NULL, -1);
5837 "invalid command", NULL, -1);
5848 pg_fatal(
"condition error in script \"%s\" command %d: %s",
5862 for (
i = 0;
ps->commands[
i] != NULL;
i++)
5906 ParseScript(
const char *script,
const char *desc,
int weight)
5916 #define COMMANDS_ALLOC_NUM 128
5953 sr =
psql_scan(sstate, &line_buf, &prompt);
5960 ps.commands[
index++] = command;
5979 "\\gset must follow an SQL command",
5987 "\\gset must follow an SQL command",
5991 if (command->
argc <= 1 || command->
argv[1][0] ==
'\0')
6006 ps.commands[
index++] = command;
6015 if (
index >= alloc_num)
6046 size_t buflen = BUFSIZ;
6055 nread = fread(
buf + used, 1, BUFSIZ,
fd);
6084 else if ((
fd = fopen(
filename,
"r")) == NULL)
6113 fprintf(stderr,
"Available builtin scripts:\n");
6145 pg_log_error(
"ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found,
name);
6164 int namelen = sep -
option;
6170 strncpy(*script,
option, namelen);
6171 (*script)[namelen] =
'\0';
6175 wtmp = strtol(sep + 1, &badp, 10);
6176 if (errno != 0 || badp == sep + 1 || *badp !=
'\0')
6177 pg_fatal(
"invalid weight specification: %s", sep);
6178 if (wtmp > INT_MAX || wtmp < 0)
6179 pg_fatal(
"weight specification out of range (0 .. %d): %lld",
6180 INT_MAX, (
long long) wtmp);
6197 pg_fatal(
"empty command list for script \"%s\"", script->
desc);
6251 cur.serialization_failures +=
6257 cnt =
cur.cnt - last->
cnt;
6258 total_run = (
now - test_start) / 1000000.0;
6259 tps = 1000000.0 * cnt / run;
6262 latency = 0.001 * (
cur.latency.sum - last->
latency.
sum) / cnt;
6264 stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
6265 lag = 0.001 * (
cur.lag.sum - last->
lag.
sum) / cnt;
6269 latency = sqlat = stdev = lag = 0;
6276 snprintf(tbuf,
sizeof(tbuf),
"%.3f s",
6282 snprintf(tbuf,
sizeof(tbuf),
"%.1f s", total_run);
6286 "progress: %s, %.1f tps, lat %.3f ms stddev %.3f, " INT64_FORMAT " failed",
6287 tbuf, tps, latency, stdev, failures);
6291 fprintf(stderr,
", lag %.3f ms", lag);
6313 double latency = ss->
sum / ss->
count;
6314 double stddev = sqrt(ss->
sum2 / ss->
count - latency * latency);
6316 printf(
"%s average = %.3f ms\n", prefix, 0.001 * latency);
6317 printf(
"%s stddev = %.3f ms\n", prefix, 0.001 * stddev);
6326 int client_ver = PG_VERSION_NUM;
6328 if (server_ver != client_ver)
6339 sverbuf,
sizeof(sverbuf));
6343 printf(
_(
"%s (%s, server %s)\n"),
6348 printf(
"%s (%s)\n",
"pgbench", PG_VERSION);
6362 int64 total_cnt = total->
cnt + total->
skipped + failures;
6364 double tps = total->
cnt / bench_duration;
6367 printf(
"transaction type: %s\n",
6372 printf(
"partition method: %s\npartitions: %d\n",
6383 printf(
"number of transactions per client: %d\n",
nxacts);
6402 failures, 100.0 * failures / total_cnt);
6429 (total->
cnt > 0) ? 100.0 * latency_late / total->
cnt : 0.0);
6436 printf(
"latency average = %.3f ms%s\n",
6437 0.001 * total_duration *
nclients / total_cnt,
6438 failures > 0 ?
" (including failures)" :
"");
6449 printf(
"rate limit schedule lag: avg %.3f (max %.3f) ms\n",
6464 printf(
"average connection time = %.3f ms\n", 0.001 * conn_total_duration / (total->
cnt + failures));
6465 printf(
"tps = %f (including reconnection times)\n", tps);
6469 printf(
"initial connection time = %.3f ms\n", 0.001 * conn_elapsed_duration);
6470 printf(
"tps = %f (without initial connection time)\n", tps);
6484 int64 script_total_cnt =
6485 sstats->
cnt + sstats->
skipped + script_failures;
6487 printf(
"SQL script %d: %s\n"
6488 " - weight: %d (targets %.1f%% of total)\n"
6489 " - " INT64_FORMAT " transactions (%.1f%% of total)\n",
6494 100.0 * script_total_cnt / total_cnt);
6496 if (script_total_cnt > 0)
6499 sstats->
cnt, sstats->
cnt / bench_duration);
6503 100.0 * script_failures / script_total_cnt);
6525 100.0 * sstats->
retried / script_total_cnt);
6533 100.0 * sstats->
skipped / script_total_cnt);
6547 printf(
"%sstatement latencies in milliseconds%s:\n",
6551 ", failures and retries"));
6560 printf(
" %11.3f %10" INT64_MODIFIER
"d %s\n",
6561 (cstats->
count > 0) ?
6562 1000.0 * cstats->
sum / cstats->
count : 0.0,
6563 (*commands)->failures,
6564 (*commands)->first_line);
6566 printf(
" %11.3f %10" INT64_MODIFIER
"d %10" INT64_MODIFIER
"d %s\n",
6567 (cstats->
count > 0) ?
6568 1000.0 * cstats->
sum / cstats->
count : 0.0,
6569 (*commands)->failures,
6570 (*commands)->retries,
6571 (*commands)->first_line);
6587 if (seed == NULL || strcmp(seed,
"time") == 0)
6592 else if (strcmp(seed,
"rand") == 0)
6604 unsigned long ulseed;
6608 if (sscanf(seed,
"%lu%c", &ulseed, &garbage) != 1)
6610 pg_log_error(
"unrecognized random seed option \"%s\"", seed);
6614 iseed = (uint64) ulseed;
6618 pg_log_info(
"setting random seed to %llu", (
unsigned long long) iseed);
6629 main(
int argc,
char **argv)
6631 static struct option long_options[] = {
6682 bool is_init_mode =
false;
6683 char *initialize_steps = NULL;
6684 bool foreign_keys =
false;
6685 bool is_no_vacuum =
false;
6686 bool do_vacuum_accounts =
false;
6688 bool scale_given =
false;
6690 bool benchmarking_option_set =
false;
6691 bool initialization_option_set =
false;
6692 bool internal_script_used =
false;
6700 conn_total_duration;
6702 int64 latency_late = 0;
6709 #ifdef HAVE_GETRLIMIT
6731 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
6736 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
6738 puts(
"pgbench (PostgreSQL) " PG_VERSION);
6747 pg_fatal(
"error while setting random seed from PGBENCH_RANDOM_SEED environment variable");
6749 while ((
c =
getopt_long(argc, argv,
"b:c:Cd:D:f:F:h:iI:j:lL:M:nNp:P:qrR:s:St:T:U:v", long_options, &optindex)) != -1)
6756 if (strcmp(
optarg,
"list") == 0)
6763 benchmarking_option_set =
true;
6764 internal_script_used =
true;
6767 benchmarking_option_set =
true;
6773 #ifdef HAVE_GETRLIMIT
6774 if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
6778 pg_log_error(
"need at least %d open files, but system limit is %ld",
6779 nclients + 3, (
long) rlim.rlim_cur);
6780 pg_log_error_hint(
"Reduce number of clients, or use limit/ulimit to increase the system limit.");
6786 benchmarking_option_set =
true;
6796 benchmarking_option_set =
true;
6798 if ((p = strchr(
optarg,
'=')) == NULL || p ==
optarg || *(p + 1) ==
'\0')
6809 benchmarking_option_set =
true;
6812 initialization_option_set =
true;
6821 is_init_mode =
true;
6827 initialization_option_set =
true;
6830 benchmarking_option_set =
true;
6838 benchmarking_option_set =
true;
6843 double limit_ms = atof(
optarg);
6845 if (limit_ms <= 0.0)
6847 benchmarking_option_set =
true;
6852 benchmarking_option_set =
true;
6860 is_no_vacuum =
true;
6864 benchmarking_option_set =
true;
6865 internal_script_used =
true;
6871 benchmarking_option_set =
true;
6877 initialization_option_set =
true;
6881 benchmarking_option_set =
true;
6887 double throttle_value = atof(
optarg);
6889 benchmarking_option_set =
true;
6891 if (throttle_value <= 0.0)
6905 benchmarking_option_set =
true;
6906 internal_script_used =
true;
6909 benchmarking_option_set =
true;
6915 benchmarking_option_set =
true;
6924 benchmarking_option_set =
true;
6925 do_vacuum_accounts =
true;
6928 initialization_option_set =
true;
6932 initialization_option_set =
true;
6936 initialization_option_set =
true;
6940 benchmarking_option_set =
true;
6942 if (sample_rate <= 0.0 || sample_rate > 1.0)
6946 benchmarking_option_set =
true;
6953 benchmarking_option_set =
true;
6956 benchmarking_option_set =
true;
6960 initialization_option_set =
true;
6961 foreign_keys =
true;
6964 benchmarking_option_set =
true;
6966 pg_fatal(
"error while setting random seed from --random-seed option");
6977 initialization_option_set =
true;
6983 initialization_option_set =
true;
6989 pg_fatal(
"invalid partition method, expecting \"range\" or \"hash\", got: \"%s\"",
6993 benchmarking_option_set =
true;
7000 if (max_tries_arg < 0)
7003 benchmarking_option_set =
true;
7008 benchmarking_option_set =
true;
7012 benchmarking_option_set =
true;
7029 benchmarking_option_set =
true;
7030 internal_script_used =
true;
7038 for (
int j = 0; commands[
j] != NULL;
j++)
7047 pg_fatal(
"total script weight must not be zero");
7074 if ((env = getenv(
"PGDATABASE")) != NULL && *env !=
'\0')
7076 else if ((env = getenv(
"PGUSER")) != NULL && *env !=
'\0')
7085 pg_log_error(
"too many command-line arguments (first is \"%s\")",
7093 if (benchmarking_option_set)
7094 pg_fatal(
"some of the specified options cannot be used in initialization (-i) mode");
7097 pg_fatal(
"--partition-method requires greater than zero --partitions");
7103 if (initialize_steps == NULL)
7111 while ((p = strchr(initialize_steps,
'v')) != NULL)
7118 if (strchr(initialize_steps,
'f') == NULL)
7120 initialize_steps = (
char *)
7122 strlen(initialize_steps) + 2);
7123 strcat(initialize_steps,
"f");
7132 if (initialization_option_set)
7133 pg_fatal(
"some of the specified options cannot be used in benchmarking mode");
7137 pg_fatal(
"specify either a number of transactions (-t) or a duration (-T), not both");
7145 pg_fatal(
"log sampling (--sampling-rate) is allowed only when logging transactions (-l)");
7149 pg_fatal(
"log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time");
7152 pg_fatal(
"log aggregation is allowed only when actually logging transactions");
7155 pg_fatal(
"log file prefix (--log-prefix) is allowed only when logging transactions (-l)");
7164 pg_fatal(
"--progress-timestamp is allowed only under --progress");
7169 pg_fatal(
"an unlimited number of transaction tries can only be used with --latency-limit or a duration (-T)");
7189 for (
j = 0;
j <
state[0].variables.nvars;
j++)
7219 pg_fatal(
"could not create connection for setup");
7224 pg_log_debug(
"pghost: %s pgport: %s nclients: %d %s: %d dbName: %s",
7226 duration <= 0 ?
"nxacts" :
"duration",
7229 if (internal_script_used)
7278 fprintf(stderr,
"starting vacuum...");
7284 if (do_vacuum_accounts)
7286 fprintf(stderr,
"starting vacuum pgbench_accounts...");
7312 nclients_dealt += thread->
nstate;
7327 pg_fatal(
"could not initialize barrier: %m");
7338 pg_fatal(
"could not create thread: %m");
7351 conn_total_duration = 0;
7360 for (
int j = 0;
j < thread->
nstate;
j++)
7377 if (bench_start == 0 || thread->
bench_start < bench_start)
7401 pg_log_error(
"Run was aborted; the above results are incomplete.");
7412 int nstate = thread->
nstate;
7413 int remains = nstate;
7427 if (thread->
tid == 0)
7432 thread->
logfile = fopen(logpath,
"w");
7435 pg_fatal(
"could not open logfile \"%s\": %m", logpath);
7439 for (
int i = 0;
i < nstate;
i++)
7448 last_report = thread_start;
7449 next_report = last_report + (int64) 1000000 *
progress;
7455 for (
int i = 0;
i < nstate;
i++)
7460 pg_fatal(
"could not create connection for client %d",
7497 for (
int i = 0;
i < nstate;
i++)
7512 if (min_usec > this_usec)
7513 min_usec = this_usec;
7549 if (
now >= next_report)
7551 else if ((next_report -
now) < min_usec)
7552 min_usec = next_report -
now;
7601 for (
int i = 0;
i < nstate;
i++)
7650 if (now2 >= next_report)
7659 &last, &last_report);
7667 next_report += (int64) 1000000 *
progress;
7668 }
while (now2 >= next_report);
7679 for (
int i = 0;
i < nstate;
i++)
7683 pg_log_error(
"Run was aborted due to an error in thread %d",
7709 if (st->
con != NULL)
7737 static VOID CALLBACK
7738 win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
7750 queue = CreateTimerQueue();
7751 if (seconds > ((DWORD) -1) / 1000 ||
7752 !CreateTimerQueueTimer(&timer, queue,
7753 win32_timer_callback, NULL, seconds * 1000, 0,
7754 WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
7796 #ifdef POLL_USING_PPOLL
7804 sizeof(
struct pollfd) * count);
7827 sa->pollfds[
idx].events = POLLIN;
7828 sa->pollfds[
idx].revents = 0;
7837 struct timespec timeout;
7839 timeout.tv_sec = usecs / 1000000;
7840 timeout.tv_nsec = (usecs % 1000000) * 1000;
7841 return ppoll(
sa->pollfds,
sa->curfds, &timeout, NULL);
7845 return ppoll(
sa->pollfds,
sa->curfds, NULL, NULL);
7860 if (
sa->curfds == 0)
7864 return (
sa->pollfds[
idx].revents & POLLIN) != 0;
7869 #ifdef POLL_USING_SELECT
7895 if (
sa->fds.fd_count + 1 >= FD_SETSIZE)
7897 pg_log_error(
"too many concurrent database clients for this platform: %d",
7898 sa->fds.fd_count + 1);
7902 if (fd < 0 || fd >= FD_SETSIZE)
7904 pg_log_error(
"socket file descriptor out of range for select(): %d",
7910 FD_SET(
fd, &
sa->fds);
7920 struct timeval timeout;
7922 timeout.tv_sec = usecs / 1000000;
7923 timeout.tv_usec = usecs % 1000000;
7924 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, &timeout);
7928 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, NULL);
7935 return (FD_ISSET(
fd, &
sa->fds) != 0);
Datum idx(PG_FUNCTION_ARGS)
Datum now(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define IS_HIGHBIT_SET(ch)
#define Assert(condition)
#define FLEXIBLE_ARRAY_MEMBER
#define FLOAT8_FITS_IN_INT64(num)
volatile sig_atomic_t CancelRequested
void ResetCancelConn(void)
void SetCancelConn(PGconn *conn)
void setup_cancel_handler(void(*query_cancel_callback)(void))
ifState conditional_stack_peek(ConditionalStack cstack)
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
ConditionalStack conditional_stack_create(void)
bool conditional_stack_pop(ConditionalStack cstack)
void conditional_stack_destroy(ConditionalStack cstack)
bool conditional_active(ConditionalStack cstack)
void conditional_stack_reset(ConditionalStack cstack)
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
bool conditional_stack_empty(ConditionalStack cstack)
static void PGresult * res
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
int PQserverVersion(const PGconn *conn)
char * PQhost(const PGconn *conn)
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
char * PQdb(const PGconn *conn)
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
int PQconnectionNeedsPassword(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
ConnStatusType PQstatus(const PGconn *conn)
void PQfinish(PGconn *conn)
char * PQport(const PGconn *conn)
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
int PQsocket(const PGconn *conn)
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
void PQfreemem(void *ptr)
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
int PQexitPipelineMode(PGconn *conn)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
int PQenterPipelineMode(PGconn *conn)
ExecStatusType PQresultStatus(const PGresult *res)
int PQendcopy(PGconn *conn)
int PQsendPipelineSync(PGconn *conn)
int PQntuples(const PGresult *res)
int PQputline(PGconn *conn, const char *string)
char * PQfname(const PGresult *res, int field_num)
PGresult * PQexec(PGconn *conn, const char *query)
int PQconsumeInput(PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQsendQuery(PGconn *conn, const char *query)
int PQpipelineSync(PGconn *conn)
int PQisBusy(PGconn *conn)
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
char * PQresultErrorField(const PGresult *res, int fieldcode)
int PQnfields(const PGresult *res)
PGresult * PQgetResult(PGconn *conn)
void * pg_realloc(void *ptr, size_t size)
void * pg_malloc0(size_t size)
char * pg_strdup(const char *in)
void * pg_malloc(size_t size)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
static const FormData_pg_attribute a1
static const FormData_pg_attribute a2
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_GET_MICROSEC(t)
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
static void const char fflush(stdout)
void pg_logging_increase_verbosity(void)
void pg_logging_init(const char *argv0)
enum pg_log_level __pg_log_level
#define pg_log_error(...)
#define pg_log_error_hint(...)
#define pg_log_error_detail(...)
#define pg_log_debug(...)
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
static int pg_leftmost_one_pos64(uint64 word)
static int server_version
PGDLLIMPORT char * optarg
double pg_prng_double(pg_prng_state *state)
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
uint64 pg_prng_uint64(pg_prng_state *state)
void pg_prng_seed(pg_prng_state *state, uint64 seed)
double pg_prng_double_normal(pg_prng_state *state)
static rewind_source * source
void syntax_error(const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
static Variable * lookupVariable(Variables *variables, char *name)
static QueryMode querymode
static char * index_tablespace
static void printResults(StatsData *total, pg_time_usec_t total_duration, pg_time_usec_t conn_total_duration, pg_time_usec_t conn_elapsed_duration, int64 latency_late)
static bool putVariableInt(Variables *variables, const char *context, char *name, int64 value)
static char * read_file_contents(FILE *fd)
static pg_time_usec_t pg_time_now(void)
bool strtodouble(const char *str, bool errorOK, double *dv)
static void accumStats(StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
#define THREAD_FUNC_RETURN_TYPE
static void initCreatePKeys(PGconn *con)
static void GetTableInfo(PGconn *con, bool scale_given)
static void printVerboseErrorMessages(CState *st, pg_time_usec_t *now, bool is_retry)
static void initRandomState(pg_prng_state *state)
static bool isLazyFunc(PgBenchFunction func)
static double throttle_delay
static bool per_script_stats
static int64 getZipfianRand(pg_prng_state *state, int64 min, int64 max, double s)
#define THREAD_BARRIER_WAIT(barrier)
static const BuiltinScript * findBuiltin(const char *name)
static void setIntValue(PgBenchValue *pv, int64 ival)
static char * getVariable(Variables *variables, char *name)
static int64 latency_limit
static THREAD_FUNC_RETURN_TYPE THREAD_FUNC_CC threadRun(void *arg)
#define SHELL_COMMAND_SIZE
static void setalarm(int seconds)
struct BuiltinScript BuiltinScript
static void initTeller(PQExpBufferData *sql, int64 curr)
static TStatus getTransactionStatus(PGconn *con)
static bool exit_on_abort
static bool coerceToInt(PgBenchValue *pval, int64 *ival)
static void setNullValue(PgBenchValue *pv)
#define SOCKET_WAIT_METHOD
static bool doRetry(CState *st, pg_time_usec_t *now)
static bool evalLazyFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
#define ERRCODE_T_R_DEADLOCK_DETECTED
static int64 getExponentialRand(pg_prng_state *state, int64 min, int64 max, double parameter)
static void free_socket_set(socket_set *sa)
static void CheckConditional(const ParsedScript *ps)
static bool sendCommand(CState *st, Command *command)
static void doLog(TState *thread, CState *st, StatsData *agg, bool skipped, double latency, double lag)
#define COMMANDS_ALLOC_NUM
#define ERRCODE_T_R_SERIALIZATION_FAILURE
static void prepareCommandsInPipeline(CState *st)
int main(int argc, char **argv)
static Variable * lookupCreateVariable(Variables *variables, const char *context, char *name)
static bool putVariable(Variables *variables, const char *context, char *name, const char *value)
static void finishCon(CState *st)
static int compareVariableNames(const void *v1, const void *v2)
static const char * getResultString(bool skipped, EStatus estatus)
static void printVersion(PGconn *con)
static void initBranch(PQExpBufferData *sql, int64 curr)
struct socket_set socket_set
static bool evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
static bool parseQuery(Command *cmd)
static void initStats(StatsData *sd, pg_time_usec_t start)
static pg_prng_state base_random_sequence
static void setDoubleValue(PgBenchValue *pv, double dval)
static void checkInitSteps(const char *initialize_steps)
static void createPartitions(PGconn *con)
static void initDropTables(PGconn *con)
static void clear_socket_set(socket_set *sa)
static void free_command(Command *command)
static void postprocess_sql_command(Command *my_command)
static bool progress_timestamp
static const char *const QUERYMODE[]
@ CSTATE_WAIT_ROLLBACK_RESULT
@ CSTATE_PREPARE_THROTTLE
static void handle_sig_alarm(SIGNAL_ARGS)
static double sample_rate
static bool evalFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
static char * valueTypeName(PgBenchValue *pval)
static bool runShellCommand(Variables *variables, char *variable, char **argv, int argc)
#define MIN_ZIPFIAN_PARAM
#define PARAMS_ARRAY_SIZE
void(* initRowMethod)(PQExpBufferData *sql, int64 curr)
static bool report_per_command
static void initGenerateDataServerSide(PGconn *con)
static bool makeVariableValue(Variable *var)
static Command * process_backslash_command(PsqlScanState sstate, const char *source)
static MetaCommand getMetaCommand(const char *cmd)
static void mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
#define THREAD_JOIN(handle)
static void printSimpleStats(const char *prefix, SimpleStats *ss)
#define ERRCODE_UNDEFINED_TABLE
static void listAvailableScripts(void)
static char * logfile_prefix
#define PG_TIME_GET_DOUBLE(t)
static bool set_random_seed(const char *seed)
static void add_socket_to_set(socket_set *sa, int fd, int idx)
static int discardUntilSync(CState *st)
static EStatus getSQLErrorStatus(const char *sqlState)
static int64 total_weight
#define THREAD_FUNC_RETURN
static ConnectionStateEnum executeMetaCommand(CState *st, pg_time_usec_t *now)
#define VARIABLES_ALLOC_MARGIN
static void initCreateFKeys(PGconn *con)
static const BuiltinScript builtin_script[]
static int64 getFailures(const StatsData *stats)
static ParsedScript sql_script[MAX_SCRIPTS]
static bool canRetryError(EStatus estatus)
static void runInitSteps(const char *initialize_steps)
static int64 permute(const int64 val, const int64 isize, const int64 seed)
static void commandFailed(CState *st, const char *cmd, const char *message)
static int chooseScript(TState *thread)
static bool evalStandardFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
static void addScript(const ParsedScript *script)
static void setBoolValue(PgBenchValue *pv, bool bval)
static void initTruncateTables(PGconn *con)
bool strtoint64(const char *str, bool errorOK, int64 *result)
@ ESTATUS_META_COMMAND_ERROR
@ ESTATUS_OTHER_SQL_ERROR
@ ESTATUS_SERIALIZATION_ERROR
struct StatsData StatsData
static int64 computeIterativeZipfian(pg_prng_state *state, int64 n, double s)
static void advanceConnectionState(TState *thread, CState *st, StatsData *agg)
static void ConditionError(const char *desc, int cmdn, const char *msg)
static bool evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
static void process_builtin(const BuiltinScript *bi, int weight)
static int parseScriptWeight(const char *option, char **script)
struct SimpleStats SimpleStats
struct ParsedScript ParsedScript
static void initVacuum(PGconn *con)
static bool putVariableValue(Variables *variables, const char *context, char *name, const PgBenchValue *value)
static void initAccount(PQExpBufferData *sql, int64 curr)
static void commandError(CState *st, const char *message)
static char * assignVariables(Variables *variables, char *sql)
static void tryExecuteStatement(PGconn *con, const char *sql)
static bool valid_variable_name(const char *name)
static partition_method_t partition_method
static int64 getrand(pg_prng_state *state, int64 min, int64 max)
static const char *const PARTITION_METHOD[]
static void getQueryParams(Variables *variables, const Command *command, const char **params)
static volatile sig_atomic_t timer_exceeded
static char * skip_sql_comments(char *sql_command)
static const char * pghost
static void enlargeVariables(Variables *variables, int needed)
static THREAD_BARRIER_T barrier
static void printProgressReport(TState *threads, int64 test_start, pg_time_usec_t now, StatsData *last, int64 *last_report)
static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
static const char * username
static bool unlogged_tables
static void initSimpleStats(SimpleStats *ss)
static int64 getHashMurmur2(int64 val, uint64 seed)
static void process_file(const char *filename, int weight)
static const PsqlScanCallbacks pgbench_callbacks
static void ParseScript(const char *script, const char *desc, int weight)
static void prepareCommand(CState *st, int command_num)
#define THREAD_BARRIER_INIT(barrier, n)
static bool socket_has_input(socket_set *sa, int fd, int idx)
static const char * progname
static bool valueTruth(PgBenchValue *pval)
static bool is_an_int(const char *str)
static void pg_time_now_lazy(pg_time_usec_t *now)
static int64 getGaussianRand(pg_prng_state *state, int64 min, int64 max, double parameter)
static void addToSimpleStats(SimpleStats *ss, double val)
static const char * pgport
static void initPopulateTable(PGconn *con, const char *table, int64 base, initRowMethod init_row)
static void allocCStatePrepared(CState *st)
static void disconnect_all(CState *state, int length)
static Command * create_sql_command(PQExpBuffer buf, const char *source)
#define DEFAULT_INIT_STEPS
static void initCreateTables(PGconn *con)
static bool verbose_errors
#define MIN_GAUSSIAN_PARAM
#define SCALE_32BIT_THRESHOLD
static const char * dbName
static int64 getPoissonRand(pg_prng_state *state, double center)
static int wait_on_socket_set(socket_set *sa, int64 usecs)
static void executeStatement(PGconn *con, const char *sql)
#define THREAD_CREATE(handle, function, arg)
static int64 getHashFnv1a(int64 val, uint64 seed)
static char * parseVariable(const char *sql, int *eaten)
static bool coerceToDouble(PgBenchValue *pval, double *dval)
static socket_set * alloc_socket_set(int count)
static bool failures_detailed
static PGconn * doConnect(void)
static void initGenerateDataClientSide(PGconn *con)
static bool readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
static pg_time_usec_t epoch_shift
static char * replaceVariable(char **sql, char *param, int len, char *value)
#define MAX_ZIPFIAN_PARAM
static bool coerceToBool(PgBenchValue *pval, bool *bval)
#define THREAD_BARRIER_DESTROY(barrier)
int expr_scanner_offset(PsqlScanState state)
@ PGBENCH_RANDOM_EXPONENTIAL
@ PGBENCH_RANDOM_GAUSSIAN
bool expr_lex_one_word(PsqlScanState state, PQExpBuffer word_buf, int *offset)
int expr_yyparse(yyscan_t yyscanner)
int expr_scanner_get_lineno(PsqlScanState state, int offset)
PgBenchExpr * expr_parse_result
void expr_scanner_finish(yyscan_t yyscanner)
yyscan_t expr_scanner_init(PsqlScanState state, const char *source, int lineno, int start_offset, const char *command)
char * expr_scanner_get_substring(PsqlScanState state, int start_offset, int end_offset, bool chomp)
#define pg_log_warning(...)
static core_yyscan_t yyscanner
int int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
bool pg_strong_random(void *buf, size_t len)
int pg_strcasecmp(const char *s1, const char *s2)
const char * get_progname(const char *argv0)
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define qsort(a, b, c, d)
size_t strlcpy(char *dst, const char *src, size_t siz)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
void initPQExpBuffer(PQExpBuffer str)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
enum _promptStatus promptStatus_t
void psql_scan_destroy(PsqlScanState state)
PsqlScanResult psql_scan(PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
void psql_scan_setup(PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
void psql_scan_finish(PsqlScanState state)
void pg_usleep(long microsec)
static pg_noinline void Size size
char * simple_prompt(const char *prompt, bool echo)
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
pg_time_usec_t txn_scheduled
pg_time_usec_t stmt_begin
pg_time_usec_t sleep_until
pg_prng_state random_state
ConnectionStateEnum state
struct PgBenchExpr::@35::@36 variable
union PgBenchValue::@34 u
int64 serialization_failures
pg_time_usec_t start_time
pg_time_usec_t create_time
pg_prng_state ts_throttle_rs
pg_time_usec_t conn_duration
pg_prng_state ts_choose_rs
pg_time_usec_t bench_start
pg_prng_state ts_sample_rs
pg_time_usec_t started_time
const char * get_user_name_or_exit(const char *progname)
#define select(n, r, w, e, timeout)
int gettimeofday(struct timeval *tp, void *tzp)
static char chars[TZ_MAX_CHARS]