mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
pgbench: Allow changing weights for scripts
Previously, all scripts had the same probability of being chosen when multiple of them were specified via -b, -f, -N, -S. With this commit, -b and -f now search for an "@" in the script name and use the integer found after it as the drawing probability for that script. (One disadvantage is that if you have script whose names contain @, you are now forced to specify "@1" at the end; otherwise the name's @ is confused with a weight separator. We don't expect many pgbench script with @ in their names in the wild, so this shouldn't be too serious a problem.) While at it, rework the interface between addScript, process_file, process_builtin, and findBuiltin. It had gotten a bit out of hand with recent commits. Author: Fabien Coelho Reviewed-By: Andres Freund, Robert Haas, Álvaro Herrera, Michaël Paquier Discussion: http://www.postgresql.org/message-id/alpine.DEB.2.10.1603160721240.1666@sto
This commit is contained in:
@ -262,11 +262,13 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
|
|||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-b</> <replaceable>scriptname</></term>
|
<term><option>-b</> <replaceable>scriptname[@weight]</></term>
|
||||||
<term><option>--builtin</> <replaceable>scriptname</></term>
|
<term><option>--builtin</>=<replaceable>scriptname[@weight]</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Add the specified builtin script to the list of executed scripts.
|
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 script. If not specified, it is set to 1.
|
||||||
Available builtin scripts are: <literal>tpcb-like</>,
|
Available builtin scripts are: <literal>tpcb-like</>,
|
||||||
<literal>simple-update</> and <literal>select-only</>.
|
<literal>simple-update</> and <literal>select-only</>.
|
||||||
Unambiguous prefixes of builtin names are accepted.
|
Unambiguous prefixes of builtin names are accepted.
|
||||||
@ -322,12 +324,14 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-f</> <replaceable>filename</></term>
|
<term><option>-f</> <replaceable>filename[@weight]</></term>
|
||||||
<term><option>--file=</><replaceable>filename</></term>
|
<term><option>--file=</><replaceable>filename[@weight]</></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Add a transaction script read from <replaceable>filename</> to
|
Add a transaction script read from <replaceable>filename</> to
|
||||||
the list of executed scripts.
|
the list of executed scripts.
|
||||||
|
An optional integer weight after <literal>@</> allows to adjust the
|
||||||
|
probability of drawing the test.
|
||||||
See below for details.
|
See below for details.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -687,9 +691,13 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
|
|||||||
<title>What is the <quote>Transaction</> Actually Performed in <application>pgbench</application>?</title>
|
<title>What is the <quote>Transaction</> Actually Performed in <application>pgbench</application>?</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Pgbench executes test scripts chosen randomly from a specified list.
|
<application>pgbench</> executes test scripts chosen randomly
|
||||||
|
from a specified list.
|
||||||
They include built-in scripts with <option>-b</> and
|
They include built-in scripts with <option>-b</> and
|
||||||
user-provided custom scripts with <option>-f</>.
|
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>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -1194,12 +1202,11 @@ number of clients: 10
|
|||||||
number of threads: 1
|
number of threads: 1
|
||||||
number of transactions per client: 1000
|
number of transactions per client: 1000
|
||||||
number of transactions actually processed: 10000/10000
|
number of transactions actually processed: 10000/10000
|
||||||
|
latency average = 15.844 ms
|
||||||
|
latency stddev = 2.715 ms
|
||||||
tps = 618.764555 (including connections establishing)
|
tps = 618.764555 (including connections establishing)
|
||||||
tps = 622.977698 (excluding connections establishing)
|
tps = 622.977698 (excluding connections establishing)
|
||||||
SQL script 1: <builtin: TPC-B (sort of)>
|
script statistics:
|
||||||
- 10000 transactions (100.0% of total, tps = 618.764555)
|
|
||||||
- latency average = 15.844 ms
|
|
||||||
- latency stddev = 2.715 ms
|
|
||||||
- statement latencies in milliseconds:
|
- statement latencies in milliseconds:
|
||||||
0.004386 \set nbranches 1 * :scale
|
0.004386 \set nbranches 1 * :scale
|
||||||
0.001343 \set ntellers 10 * :scale
|
0.001343 \set ntellers 10 * :scale
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "portability/instr_time.h"
|
#include "portability/instr_time.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -180,6 +181,8 @@ char *login = NULL;
|
|||||||
char *dbName;
|
char *dbName;
|
||||||
const char *progname;
|
const char *progname;
|
||||||
|
|
||||||
|
#define WSEP '@' /* weight separator */
|
||||||
|
|
||||||
volatile bool timer_exceeded = false; /* flag from signal handler */
|
volatile bool timer_exceeded = false; /* flag from signal handler */
|
||||||
|
|
||||||
/* variable definitions */
|
/* variable definitions */
|
||||||
@ -298,26 +301,30 @@ typedef struct
|
|||||||
SimpleStats stats; /* time spent in this command */
|
SimpleStats stats; /* time spent in this command */
|
||||||
} Command;
|
} Command;
|
||||||
|
|
||||||
static struct
|
typedef struct ParsedScript
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *desc;
|
||||||
|
int weight;
|
||||||
Command **commands;
|
Command **commands;
|
||||||
StatsData stats;
|
StatsData stats;
|
||||||
} sql_script[MAX_SCRIPTS]; /* SQL script files */
|
} ParsedScript;
|
||||||
|
|
||||||
|
static ParsedScript sql_script[MAX_SCRIPTS]; /* SQL script files */
|
||||||
static int num_scripts; /* number of scripts in sql_script[] */
|
static int num_scripts; /* number of scripts in sql_script[] */
|
||||||
static int num_commands = 0; /* total number of Command structs */
|
static int num_commands = 0; /* total number of Command structs */
|
||||||
|
static int64 total_weight = 0;
|
||||||
|
|
||||||
static int debug = 0; /* debug flag */
|
static int debug = 0; /* debug flag */
|
||||||
|
|
||||||
/* Define builtin test scripts */
|
/* Builtin test scripts */
|
||||||
#define N_BUILTIN 3
|
typedef struct BuiltinScript
|
||||||
static struct
|
|
||||||
{
|
{
|
||||||
char *name; /* very short name for -b ... */
|
char *name; /* very short name for -b ... */
|
||||||
char *desc; /* short description */
|
char *desc; /* short description */
|
||||||
char *commands; /* actual pgbench script */
|
char *script; /* actual pgbench script */
|
||||||
}
|
} BuiltinScript;
|
||||||
|
|
||||||
builtin_script[] =
|
static BuiltinScript builtin_script[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"tpcb-like",
|
"tpcb-like",
|
||||||
@ -393,9 +400,9 @@ usage(void)
|
|||||||
" --tablespace=TABLESPACE create tables in the specified tablespace\n"
|
" --tablespace=TABLESPACE create tables in the specified tablespace\n"
|
||||||
" --unlogged-tables create tables as unlogged tables\n"
|
" --unlogged-tables create tables as unlogged tables\n"
|
||||||
"\nOptions to select what to run:\n"
|
"\nOptions to select what to run:\n"
|
||||||
" -b, --builtin=NAME add buitin script (use \"-b list\" to display\n"
|
" -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
|
||||||
" available scripts)\n"
|
" (use \"-b list\" to list available scripts)\n"
|
||||||
" -f, --file=FILENAME add transaction script from FILENAME\n"
|
" -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
|
||||||
" -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
|
" -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
|
||||||
" (same as \"-b simple-update\")\n"
|
" (same as \"-b simple-update\")\n"
|
||||||
" -S, --select-only perform SELECT-only transactions\n"
|
" -S, --select-only perform SELECT-only transactions\n"
|
||||||
@ -1313,13 +1320,23 @@ clientDone(CState *st, bool ok)
|
|||||||
return false; /* always false */
|
return false; /* always false */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return a script number with a weighted choice. */
|
||||||
static int
|
static int
|
||||||
chooseScript(TState *thread)
|
chooseScript(TState *thread)
|
||||||
{
|
{
|
||||||
|
int i = 0;
|
||||||
|
int64 w;
|
||||||
|
|
||||||
if (num_scripts == 1)
|
if (num_scripts == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return getrand(thread, 0, num_scripts - 1);
|
w = getrand(thread, 0, total_weight - 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
w -= sql_script[i++].weight;
|
||||||
|
} while (w >= 0);
|
||||||
|
|
||||||
|
return i - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return false iff client should be disconnected */
|
/* return false iff client should be disconnected */
|
||||||
@ -1493,7 +1510,7 @@ top:
|
|||||||
commands = sql_script[st->use_file].commands;
|
commands = sql_script[st->use_file].commands;
|
||||||
if (debug)
|
if (debug)
|
||||||
fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
|
fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
|
||||||
sql_script[st->use_file].name);
|
sql_script[st->use_file].desc);
|
||||||
st->is_throttled = false;
|
st->is_throttled = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2632,34 +2649,33 @@ read_line_from_file(FILE *fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a file name, read it and return the array of Commands contained
|
* Given a file name, read it and return its ParsedScript representation. "-"
|
||||||
* therein. "-" means to read stdin.
|
* means to read stdin.
|
||||||
*/
|
*/
|
||||||
static Command **
|
static ParsedScript
|
||||||
process_file(char *filename)
|
process_file(char *filename)
|
||||||
{
|
{
|
||||||
#define COMMANDS_ALLOC_NUM 128
|
#define COMMANDS_ALLOC_NUM 128
|
||||||
|
ParsedScript ps;
|
||||||
Command **my_commands;
|
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int lineno,
|
int lineno,
|
||||||
index;
|
index;
|
||||||
char *buf;
|
char *buf;
|
||||||
int alloc_num;
|
int alloc_num;
|
||||||
|
|
||||||
alloc_num = COMMANDS_ALLOC_NUM;
|
|
||||||
my_commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
|
|
||||||
|
|
||||||
if (strcmp(filename, "-") == 0)
|
if (strcmp(filename, "-") == 0)
|
||||||
fd = stdin;
|
fd = stdin;
|
||||||
else if ((fd = fopen(filename, "r")) == NULL)
|
else if ((fd = fopen(filename, "r")) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not open file \"%s\": %s\n",
|
fprintf(stderr, "could not open file \"%s\": %s\n",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
pg_free(my_commands);
|
exit(1);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alloc_num = COMMANDS_ALLOC_NUM;
|
||||||
|
ps.commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
|
||||||
|
ps.desc = filename;
|
||||||
|
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
@ -2676,35 +2692,36 @@ process_file(char *filename)
|
|||||||
if (command == NULL)
|
if (command == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
my_commands[index] = command;
|
ps.commands[index] = command;
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (index >= alloc_num)
|
if (index >= alloc_num)
|
||||||
{
|
{
|
||||||
alloc_num += COMMANDS_ALLOC_NUM;
|
alloc_num += COMMANDS_ALLOC_NUM;
|
||||||
my_commands = pg_realloc(my_commands, sizeof(Command *) * alloc_num);
|
ps.commands = pg_realloc(ps.commands, sizeof(Command *) * alloc_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
|
||||||
my_commands[index] = NULL;
|
ps.commands[index] = NULL;
|
||||||
|
|
||||||
return my_commands;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Command **
|
/* Parse the given builtin script and return the parsed representation */
|
||||||
process_builtin(const char *tb, const char *source)
|
static ParsedScript
|
||||||
|
process_builtin(BuiltinScript *bi)
|
||||||
{
|
{
|
||||||
#define COMMANDS_ALLOC_NUM 128
|
|
||||||
|
|
||||||
Command **my_commands;
|
|
||||||
int lineno,
|
int lineno,
|
||||||
index;
|
index;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int alloc_num;
|
int alloc_num;
|
||||||
|
char *tb = bi->script;
|
||||||
|
ParsedScript ps;
|
||||||
|
|
||||||
alloc_num = COMMANDS_ALLOC_NUM;
|
alloc_num = COMMANDS_ALLOC_NUM;
|
||||||
my_commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
|
ps.desc = bi->desc;
|
||||||
|
ps.commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
|
||||||
|
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
index = 0;
|
index = 0;
|
||||||
@ -2714,6 +2731,7 @@ process_builtin(const char *tb, const char *source)
|
|||||||
char *p;
|
char *p;
|
||||||
Command *command;
|
Command *command;
|
||||||
|
|
||||||
|
/* buffer overflow check? */
|
||||||
p = buf;
|
p = buf;
|
||||||
while (*tb && *tb != '\n')
|
while (*tb && *tb != '\n')
|
||||||
*p++ = *tb++;
|
*p++ = *tb++;
|
||||||
@ -2728,58 +2746,58 @@ process_builtin(const char *tb, const char *source)
|
|||||||
|
|
||||||
lineno += 1;
|
lineno += 1;
|
||||||
|
|
||||||
command = process_commands(buf, source, lineno);
|
command = process_commands(buf, bi->desc, lineno);
|
||||||
if (command == NULL)
|
if (command == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
my_commands[index] = command;
|
ps.commands[index] = command;
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (index >= alloc_num)
|
if (index >= alloc_num)
|
||||||
{
|
{
|
||||||
alloc_num += COMMANDS_ALLOC_NUM;
|
alloc_num += COMMANDS_ALLOC_NUM;
|
||||||
my_commands = pg_realloc(my_commands, sizeof(Command *) * alloc_num);
|
ps.commands = pg_realloc(ps.commands, sizeof(Command *) * alloc_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my_commands[index] = NULL;
|
ps.commands[index] = NULL;
|
||||||
|
|
||||||
return my_commands;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* show available builtin scripts */
|
||||||
static void
|
static void
|
||||||
listAvailableScripts(void)
|
listAvailableScripts(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr, "Available builtin scripts:\n");
|
fprintf(stderr, "Available builtin scripts:\n");
|
||||||
for (i = 0; i < N_BUILTIN; i++)
|
for (i = 0; i < lengthof(builtin_script); i++)
|
||||||
fprintf(stderr, "\t%s\n", builtin_script[i].name);
|
fprintf(stderr, "\t%s\n", builtin_script[i].name);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return builtin script "name" if unambiguous */
|
/* return builtin script "name" if unambiguous, of fails if not found */
|
||||||
static char *
|
static BuiltinScript *
|
||||||
findBuiltin(const char *name, char **desc)
|
findBuiltin(const char *name)
|
||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
found = 0,
|
found = 0,
|
||||||
len = strlen(name);
|
len = strlen(name);
|
||||||
char *commands = NULL;
|
BuiltinScript *result = NULL;
|
||||||
|
|
||||||
for (i = 0; i < N_BUILTIN; i++)
|
for (i = 0; i < lengthof(builtin_script); i++)
|
||||||
{
|
{
|
||||||
if (strncmp(builtin_script[i].name, name, len) == 0)
|
if (strncmp(builtin_script[i].name, name, len) == 0)
|
||||||
{
|
{
|
||||||
*desc = builtin_script[i].desc;
|
result = &builtin_script[i];
|
||||||
commands = builtin_script[i].commands;
|
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok, unambiguous result */
|
/* ok, unambiguous result */
|
||||||
if (found == 1)
|
if (found == 1)
|
||||||
return commands;
|
return result;
|
||||||
|
|
||||||
/* error cases */
|
/* error cases */
|
||||||
if (found == 0)
|
if (found == 0)
|
||||||
@ -2792,13 +2810,61 @@ findBuiltin(const char *name, char **desc)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*
|
||||||
addScript(const char *name, Command **commands)
|
* Determine the weight specification from a script option (-b, -f), if any,
|
||||||
|
* and return it as an integer (1 is returned if there's no weight). The
|
||||||
|
* script name is returned in *script as a malloc'd string.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parseScriptWeight(const char *option, char **script)
|
||||||
{
|
{
|
||||||
if (commands == NULL ||
|
char *sep;
|
||||||
commands[0] == NULL)
|
int weight;
|
||||||
|
|
||||||
|
if ((sep = strrchr(option, WSEP)))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "empty command list for script \"%s\"\n", name);
|
int namelen = sep - option;
|
||||||
|
long wtmp;
|
||||||
|
char *badp;
|
||||||
|
|
||||||
|
/* generate the script name */
|
||||||
|
*script = pg_malloc(namelen + 1);
|
||||||
|
strncpy(*script, option, namelen);
|
||||||
|
(*script)[namelen] = '\0';
|
||||||
|
|
||||||
|
/* process digits of the weight spec */
|
||||||
|
errno = 0;
|
||||||
|
wtmp = strtol(sep + 1, &badp, 10);
|
||||||
|
if (errno != 0 || badp == sep + 1 || *badp != '\0')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "invalid weight specification: %s\n", sep);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (wtmp > INT_MAX || wtmp <= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"weight specification out of range (1 .. %u): " INT64_FORMAT "\n",
|
||||||
|
INT_MAX, (int64) wtmp);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
weight = wtmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*script = pg_strdup(option);
|
||||||
|
weight = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append a script to the list of scripts to process */
|
||||||
|
static void
|
||||||
|
addScript(ParsedScript script, int weight)
|
||||||
|
{
|
||||||
|
if (script.commands == NULL || script.commands[0] == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "empty command list for script \"%s\"\n", script.desc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2808,8 +2874,8 @@ addScript(const char *name, Command **commands)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sql_script[num_scripts].name = name;
|
sql_script[num_scripts] = script;
|
||||||
sql_script[num_scripts].commands = commands;
|
sql_script[num_scripts].weight = weight;
|
||||||
initStats(&sql_script[num_scripts].stats, 0.0);
|
initStats(&sql_script[num_scripts].stats, 0.0);
|
||||||
num_scripts++;
|
num_scripts++;
|
||||||
}
|
}
|
||||||
@ -2840,7 +2906,7 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
|
|||||||
(INSTR_TIME_GET_DOUBLE(conn_total_time) / nclients));
|
(INSTR_TIME_GET_DOUBLE(conn_total_time) / nclients));
|
||||||
|
|
||||||
printf("transaction type: %s\n",
|
printf("transaction type: %s\n",
|
||||||
num_scripts == 1 ? sql_script[0].name : "multiple scripts");
|
num_scripts == 1 ? sql_script[0].desc : "multiple scripts");
|
||||||
printf("scaling factor: %d\n", scale);
|
printf("scaling factor: %d\n", scale);
|
||||||
printf("query mode: %s\n", QUERYMODE[querymode]);
|
printf("query mode: %s\n", QUERYMODE[querymode]);
|
||||||
printf("number of clients: %d\n", nclients);
|
printf("number of clients: %d\n", nclients);
|
||||||
@ -2894,19 +2960,24 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
|
|||||||
printf("tps = %f (including connections establishing)\n", tps_include);
|
printf("tps = %f (including connections establishing)\n", tps_include);
|
||||||
printf("tps = %f (excluding connections establishing)\n", tps_exclude);
|
printf("tps = %f (excluding connections establishing)\n", tps_exclude);
|
||||||
|
|
||||||
/* Report per-command statistics */
|
/* Report per-script/command statistics */
|
||||||
if (per_script_stats)
|
if (per_script_stats || latency_limit || is_latencies)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < num_scripts; i++)
|
for (i = 0; i < num_scripts; i++)
|
||||||
{
|
{
|
||||||
printf("SQL script %d: %s\n"
|
if (num_scripts > 1)
|
||||||
" - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
|
printf("SQL script %d: %s\n"
|
||||||
i + 1, sql_script[i].name,
|
" - weight = %d\n"
|
||||||
sql_script[i].stats.cnt,
|
" - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
|
||||||
100.0 * sql_script[i].stats.cnt / total->cnt,
|
i + 1, sql_script[i].desc,
|
||||||
sql_script[i].stats.cnt / time_include);
|
sql_script[i].weight,
|
||||||
|
sql_script[i].stats.cnt,
|
||||||
|
100.0 * sql_script[i].stats.cnt / total->cnt,
|
||||||
|
sql_script[i].stats.cnt / time_include);
|
||||||
|
else
|
||||||
|
printf("script statistics:\n");
|
||||||
|
|
||||||
if (latency_limit)
|
if (latency_limit)
|
||||||
printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
|
printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
|
||||||
@ -2914,7 +2985,8 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
|
|||||||
100.0 * sql_script[i].stats.skipped /
|
100.0 * sql_script[i].stats.skipped /
|
||||||
(sql_script[i].stats.skipped + sql_script[i].stats.cnt));
|
(sql_script[i].stats.skipped + sql_script[i].stats.cnt));
|
||||||
|
|
||||||
printSimpleStats(" - latency", &sql_script[i].stats.latency);
|
if (num_scripts > 1)
|
||||||
|
printSimpleStats(" - latency", &sql_script[i].stats.latency);
|
||||||
|
|
||||||
/* Report per-command latencies */
|
/* Report per-command latencies */
|
||||||
if (is_latencies)
|
if (is_latencies)
|
||||||
@ -2997,7 +3069,7 @@ main(int argc, char **argv)
|
|||||||
instr_time conn_total_time;
|
instr_time conn_total_time;
|
||||||
int64 latency_late = 0;
|
int64 latency_late = 0;
|
||||||
StatsData stats;
|
StatsData stats;
|
||||||
char *desc;
|
int weight;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int nclients_dealt;
|
int nclients_dealt;
|
||||||
@ -3045,6 +3117,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "ih:nvp:dqb:SNc:j:Crs:t:T:U:lf:D:F:M:P:R:L:", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "ih:nvp:dqb:SNc:j:Crs:t:T:U:lf:D:F:M:P:R:L:", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
|
char *script;
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'i':
|
case 'i':
|
||||||
@ -3176,27 +3250,25 @@ main(int argc, char **argv)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
addScript(desc,
|
weight = parseScriptWeight(optarg, &script);
|
||||||
process_builtin(findBuiltin(optarg, &desc), desc));
|
addScript(process_builtin(findBuiltin(script)), weight);
|
||||||
benchmarking_option_set = true;
|
benchmarking_option_set = true;
|
||||||
internal_script_used = true;
|
internal_script_used = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
addScript(desc,
|
addScript(process_builtin(findBuiltin("select-only")), 1);
|
||||||
process_builtin(findBuiltin("select-only", &desc),
|
|
||||||
desc));
|
|
||||||
benchmarking_option_set = true;
|
benchmarking_option_set = true;
|
||||||
internal_script_used = true;
|
internal_script_used = true;
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
addScript(desc,
|
addScript(process_builtin(findBuiltin("simple-update")), 1);
|
||||||
process_builtin(findBuiltin("simple-update", &desc),
|
|
||||||
desc));
|
|
||||||
benchmarking_option_set = true;
|
benchmarking_option_set = true;
|
||||||
internal_script_used = true;
|
internal_script_used = true;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
addScript(optarg, process_file(optarg));
|
weight = parseScriptWeight(optarg, &script);
|
||||||
|
addScript(process_file(script), weight);
|
||||||
benchmarking_option_set = true;
|
benchmarking_option_set = true;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
@ -3334,12 +3406,16 @@ main(int argc, char **argv)
|
|||||||
/* set default script if none */
|
/* set default script if none */
|
||||||
if (num_scripts == 0 && !is_init_mode)
|
if (num_scripts == 0 && !is_init_mode)
|
||||||
{
|
{
|
||||||
addScript(desc,
|
addScript(process_builtin(findBuiltin("tpcb-like")), 1);
|
||||||
process_builtin(findBuiltin("tpcb-like", &desc), desc));
|
|
||||||
benchmarking_option_set = true;
|
benchmarking_option_set = true;
|
||||||
internal_script_used = true;
|
internal_script_used = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* compute total_weight */
|
||||||
|
for (i = 0; i < num_scripts; i++)
|
||||||
|
/* cannot overflow: weight is 32b, total_weight 64b */
|
||||||
|
total_weight += sql_script[i].weight;
|
||||||
|
|
||||||
/* show per script stats if several scripts are used */
|
/* show per script stats if several scripts are used */
|
||||||
if (num_scripts > 1)
|
if (num_scripts > 1)
|
||||||
per_script_stats = true;
|
per_script_stats = true;
|
||||||
@ -3745,7 +3821,7 @@ threadRun(void *arg)
|
|||||||
commands = sql_script[st->use_file].commands;
|
commands = sql_script[st->use_file].commands;
|
||||||
if (debug)
|
if (debug)
|
||||||
fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
|
fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
|
||||||
sql_script[st->use_file].name);
|
sql_script[st->use_file].desc);
|
||||||
if (!doCustom(thread, st, &aggs))
|
if (!doCustom(thread, st, &aggs))
|
||||||
remains--; /* I've aborted */
|
remains--; /* I've aborted */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user