pgbench-script-stats-12-b.patch
text/x-diff
Filename: pgbench-script-stats-12-b.patch
Type: text/x-diff
Part: 1
Patch
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/pgbench.sgml | 13 | 6 |
| src/bin/pgbench/pgbench.c | 62 | 11 |
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 21182a7..ea0aa40 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -262,11 +262,13 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
<variablelist>
<varlistentry>
- <term><option>-b</> <replaceable>scriptname</></term>
- <term><option>--builtin</> <replaceable>scriptname</></term>
+ <term><option>-b</> <replaceable>scriptname[@weight]</></term>
+ <term><option>--builtin</> <replaceable>scriptname[@weight]</></term>
<listitem>
<para>
Add the specified builtin script to the list of executed scripts.
+ An optional integer weight after <literal>@</> allows to adjust the
+ probability of drawing the test.
Available builtin scripts are: <literal>tpcb-like</>,
<literal>simple-update</> and <literal>select-only</>.
The provided <replaceable>scriptname</> needs only to be a prefix
@@ -324,12 +326,14 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
</varlistentry>
<varlistentry>
- <term><option>-f</> <replaceable>filename</></term>
- <term><option>--file=</><replaceable>filename</></term>
+ <term><option>-f</> <replaceable>filename[@weight]</></term>
+ <term><option>--file=</><replaceable>filename[@weight]</></term>
<listitem>
<para>
Add a transaction script read from <replaceable>filename</> to
the list of executed scripts.
+ An optional integer weight after <literal>@</> allows to adjust the
+ probability of drawing the test.
See below for details.
</para>
</listitem>
@@ -421,7 +425,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
<listitem>
<para>
Run builtin simple-update script.
- Shorthand for <option>-b simple-update</>.
+ Shorthand for <option>-b simple-update@1</>.
</para>
</listitem>
</varlistentry>
@@ -539,7 +543,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
<listitem>
<para>
Run built-in select-only script.
- Shorthand for <option>-b select-only</>.
+ Shorthand for <option>-b select-only@1</>.
</para>
</listitem>
</varlistentry>
@@ -692,6 +696,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
Pgbench executes test scripts chosen randomly from a specified list.
They include built-in scripts with <option>-b</> and
user-provided custom scripts with <option>-f</>.
+ Each script may be given a relative weight specified after a
+ <literal>@</> so as to change its drawing probability.
+ The default weight is <literal>1</>.
</para>
<para>
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index b75cd80..cd2c0f3 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -179,6 +179,8 @@ char *login = NULL;
char *dbName;
const char *progname;
+#define WSEP '@' /* weight separator */
+
volatile bool timer_exceeded = false; /* flag from signal handler */
/* variable definitions */
@@ -301,6 +303,7 @@ typedef struct
typedef struct
{
const char *name;
+ int weight;
Command **commands;
StatsData stats;
} SQLScript;
@@ -308,6 +311,7 @@ typedef struct
static SQLScript sql_script[MAX_SCRIPTS];
static int num_scripts; /* number of script in sql_script[] */
static int num_commands = 0; /* total number of Command structs */
+static int total_weight = 0;
static int debug = 0; /* debug flag */
@@ -404,13 +408,13 @@ usage(void)
" --tablespace=TABLESPACE create tables in the specified tablespace\n"
" --unlogged-tables create tables as unlogged tables\n"
"\nBenchmarking options:\n"
- " -b, --builtin=NAME add buitin script among \"tpcb-like\"\n"
+ " -b, --builtin=NAME@W add weighted buitin script among \"tpcb-like\"\n"
" \"simple-update\" and \"select-only\".\n"
" -c, --client=NUM number of concurrent database clients (default: 1)\n"
" -C, --connect establish new connection for each transaction\n"
" -D, --define=VARNAME=VALUE\n"
" define variable for use by custom script\n"
- " -f, --file=FILENAME add transaction script from FILENAME\n"
+ " -f, --file=FILENAME@W add weighted transaction script from FILENAME\n"
" -j, --jobs=NUM number of threads (default: 1)\n"
" -l, --log write transaction times to log file\n"
" -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
@@ -1187,7 +1191,13 @@ clientDone(CState *st, bool ok)
static int
chooseScript(TState *thread)
{
- return getrand(thread, 0, num_scripts - 1);
+ int i = 0, w = 0, wc = (int) getrand(thread, 0, total_weight - 1);
+
+ do {
+ w += sql_script[i++].weight;
+ } while (w <= wc);
+
+ return i - 1;
}
/* return false iff client should be disconnected */
@@ -2616,8 +2626,41 @@ process_builtin(const char *tb, const char *source)
return my_commands;
}
+/* Possiby truncate option and return weight */
+static int
+getWeight(char *option)
+{
+ char *sep;
+ int weight;
+
+ if ((sep = strrchr(option, WSEP)))
+ {
+ char *s;
+ *sep++ = '\0';
+
+ /* check that the weight is a positive integer */
+ s = sep;
+ while ('0' <= *s && *s <= '9')
+ s++;
+ if (*s != '\0' || s == sep)
+ {
+ /* empty or any other char */
+ fprintf(stderr,
+ "weight for script \"%s\" must be an integer, got \"%s\"\n",
+ option, sep);
+ exit(1);
+ }
+
+ weight = atoi(sep);
+ }
+ else
+ weight = 1;
+
+ return weight;
+}
+
static void
-addScript(const char *name, Command ** commands)
+addScript(const char *name, Command ** commands, int weight)
{
if (commands == NULL)
{
@@ -2632,6 +2675,7 @@ addScript(const char *name, Command ** commands)
}
sql_script[num_scripts].name = name;
+ sql_script[num_scripts].weight = weight;
sql_script[num_scripts].commands = commands;
initStats(& sql_script[num_scripts].stats, 0.0);
num_scripts++;
@@ -2721,9 +2765,9 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
for (i = 0; i < num_scripts; i++)
{
- printf("SQL script %d: %s\n"
+ printf("SQL script %d, weight %d: %s\n"
" - "INT64_FORMAT" transactions (%.1f%% of total, tps = %f)\n",
- i+1, sql_script[i].name,
+ i+1, sql_script[i].weight, sql_script[i].name,
sql_script[i].stats.cnt,
100.0 * sql_script[i].stats.cnt / total->cnt,
sql_script[i].stats.cnt / time_include);
@@ -2814,6 +2858,7 @@ main(int argc, char **argv)
instr_time conn_total_time;
int64 latency_late = 0;
StatsData stats;
+ int weight;
char *desc;
int i;
@@ -2998,25 +3043,27 @@ main(int argc, char **argv)
exit(0);
}
+ weight = getWeight(optarg);
addScript(desc, process_builtin(
- find_builtin(optarg, &desc), desc));
+ find_builtin(optarg, &desc), desc), weight);
benchmarking_option_set = true;
internal_script_used = true;
break;
case 'S':
addScript(desc, process_builtin(
- find_builtin("select-only", &desc), desc));
+ find_builtin("select-only", &desc), desc), 1);
benchmarking_option_set = true;
internal_script_used = true;
break;
case 'N':
addScript(desc, process_builtin(
- find_builtin("simple-update", &desc), desc));
+ find_builtin("simple-update", &desc), desc), 1);
benchmarking_option_set = true;
internal_script_used = true;
break;
case 'f':
- addScript(optarg, process_file(optarg));
+ weight = getWeight(optarg);
+ addScript(optarg, process_file(optarg), weight);
benchmarking_option_set = true;
break;
case 'D':
@@ -3155,11 +3202,15 @@ main(int argc, char **argv)
if (num_scripts == 0 && !is_init_mode)
{
addScript(desc, process_builtin(
- find_builtin("tpcb-like", &desc), desc));
+ find_builtin("tpcb-like", &desc), desc), 1);
benchmarking_option_set = true;
internal_script_used = true;
}
+ /* compute total_weight */
+ for (i = 0; i < num_scripts; i++)
+ total_weight += sql_script[i].weight;
+
/* show per script stats if several scripts are used */
if (!initialization_option_set && num_scripts > 1)
per_script_stats = true;