Hello Michaƫl,
Two rebase attached.
- 15-e: prefix selection for -b
- if (strncmp(builtin_script[i].name, name, - strlen(builtin_script[i].name)) == 0) + if (strncmp(builtin_script[i].name, name, len) == 0) I agree with Alvaro here: this should remain unchanged. It seems to be a rebase mistake.
I do not understand. I tested it and it works as expected. If I put the above strlen instead the suffix detection does not work:
fabien@sto:bin/pgbench> git diff diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 783cbf9..0c33012 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -2684,7 +2684,7 @@ findBuiltin(const char *name, char **desc) for (i = 0; i < N_BUILTIN; i++) { - if (strncmp(builtin_script[i].name, name, len) == 0) + if (strncmp(builtin_script[i].name, name, strlen(builtin_script[i].name)) == 0) { *desc = builtin_script[i].desc; commands = builtin_script[i].commands; ./pgbench -b t no builtin script found for name "t" Available builtin scripts: tpcb-like simple-update select-onlyIndeed, then it can only match if the provided "name" is as long as the recorded len. The point of the "suffix" selection is to align to the short supplied string.
-- Fabien.
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index ade1b53..ca3e158 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</>. With special name <literal>list</>, show the list of builtin scripts @@ -321,12 +323,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> @@ -689,6 +693,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> @@ -1137,7 +1144,7 @@ number of transactions per client: 1000 number of transactions actually processed: 10000/10000 tps = 618.764555 (including connections establishing) tps = 622.977698 (excluding connections establishing) -SQL script 1: <builtin: TPC-B (sort of)> +SQL script 1, weight 1: <builtin: TPC-B (sort of)> - 10000 transactions (100.0% of total, tps = 618.764555) - latency average = 15.844 ms - latency stddev = 2.715 ms diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 7eb6a2d..5d24768 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 */ @@ -299,11 +301,14 @@ typedef struct static struct { const char *name; + int weight; Command **commands; StatsData stats; } sql_script[MAX_SCRIPTS]; /* SQL script files */ static int num_scripts; /* number of scripts in sql_script[] */ static int num_commands = 0; /* total number of Command structs */ +static int total_weight = 0; + static int debug = 0; /* debug flag */ /* Define builtin test scripts */ @@ -389,9 +394,9 @@ usage(void) " --tablespace=TABLESPACE create tables in the specified tablespace\n" " --unlogged-tables create tables as unlogged tables\n" "\nOptions to select what to run:\n" - " -b, --builtin=NAME add buitin script (use \"-b list\" to display\n" - " available scripts)\n" - " -f, --file=FILENAME add transaction script from FILENAME\n" + " -b, --builtin=NAME[@W] add weighted buitin script (use \"-b list\"\n" + " to display available scripts)\n" + " -f, --file=FILENAME[@W] add weighted transaction script from FILENAME\n" " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n" " (same as \"-b simple-update\")\n" " -S, --select-only perform SELECT-only transactions\n" @@ -1238,10 +1243,17 @@ clientDone(CState *st, bool ok) static int chooseScript(TState *thread) { + int i = 0, w = 0, wc; + if (num_scripts == 1) return 0; - return getrand(thread, 0, num_scripts - 1); + 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 */ @@ -2683,8 +2695,41 @@ findBuiltin(const char *name, char **desc) exit(1); } +/* 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) { @@ -2699,6 +2744,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++; @@ -2791,9 +2837,9 @@ printResults(TState *threads, StatsData *total, instr_time total_time, for (i = 0; i < num_scripts; i++) { - printf("SQL script %d: %s\n" - " - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n", - i + 1, sql_script[i].name, + printf("SQL script %d, weight %d: %s\n" + " - "INT64_FORMAT" transactions (%.1f%% of total, tps = %f)\n", + 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); @@ -2887,6 +2933,7 @@ main(int argc, char **argv) instr_time conn_total_time; int64 latency_late = 0; StatsData stats; + int weight; char *desc; int i; @@ -3066,27 +3113,32 @@ main(int argc, char **argv) exit(0); } + weight = getWeight(optarg); addScript(desc, - process_builtin(findBuiltin(optarg, &desc), desc)); + process_builtin(findBuiltin(optarg, &desc), desc), + weight); benchmarking_option_set = true; internal_script_used = true; break; case 'S': addScript(desc, process_builtin(findBuiltin("select-only", &desc), - desc)); + desc), + 1); benchmarking_option_set = true; internal_script_used = true; break; case 'N': addScript(desc, process_builtin(findBuiltin("simple-update", &desc), - 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': @@ -3225,11 +3277,16 @@ main(int argc, char **argv) if (num_scripts == 0 && !is_init_mode) { addScript(desc, - process_builtin(findBuiltin("tpcb-like", &desc), desc)); + process_builtin(findBuiltin("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 (num_scripts > 1) per_script_stats = true;
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index ca3e158..52dc142 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -271,6 +271,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</> 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 be an unambiguous + prefix of the builtin name, hence <literal>si</> would be enough to + select <literal>simple-update</>. With special name <literal>list</>, show the list of builtin scripts and exit immediately. </para> diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 5d24768..783cbf9 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -2675,22 +2675,32 @@ listAvailableScripts(void) fprintf(stderr, "\n"); } +/* return commands for selected builtin script, if unambiguous */ static char * findBuiltin(const char *name, char **desc) { - int i; + int i, found = 0, len = strlen(name); + char *commands = NULL; for (i = 0; i < N_BUILTIN; i++) { - if (strncmp(builtin_script[i].name, name, - strlen(builtin_script[i].name)) == 0) + if (strncmp(builtin_script[i].name, name, len) == 0) { *desc = builtin_script[i].desc; - return builtin_script[i].commands; + commands = builtin_script[i].commands; + found++; } } - fprintf(stderr, "no builtin script found for name \"%s\"\n", name); + if (found == 1) + return commands; + + /* error cases */ + if (found == 0) + fprintf(stderr, "no builtin script found for name \"%s\"\n", name); + else /* found > 1 */ + fprintf(stderr, + "%d builtin scripts found for prefix \"%s\"\n", found, name); listAvailableScripts(); exit(1); }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers