Commit 1d0c3b3f authored by Alvaro Herrera's avatar Alvaro Herrera

pgbench: allow per-script statistics

Provide per-script statistical info (count of transactions executed
under that script, average latency for the whole script) after a
multi-script run, adding an intermediate level of detail to existing
global stats and per-command stats.

Author: Fabien Coelho
Reviewer: Michaël Paquier, Álvaro Herrera
parent 64f5edca
...@@ -1138,6 +1138,9 @@ number of transactions actually processed: 10000/10000 ...@@ -1138,6 +1138,9 @@ number of transactions actually processed: 10000/10000
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)> SQL script 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
- 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
......
...@@ -164,6 +164,7 @@ bool use_log; /* log transaction latencies to a file */ ...@@ -164,6 +164,7 @@ bool use_log; /* log transaction latencies to a file */
bool use_quiet; /* quiet logging onto stderr */ bool use_quiet; /* quiet logging onto stderr */
int agg_interval; /* log aggregates instead of individual int agg_interval; /* log aggregates instead of individual
* transactions */ * transactions */
bool per_script_stats = false; /* whether to collect stats per script */
int progress = 0; /* thread progress report every this seconds */ int progress = 0; /* thread progress report every this seconds */
bool progress_timestamp = false; /* progress report with Unix time */ bool progress_timestamp = false; /* progress report with Unix time */
int nclients = 1; /* number of clients */ int nclients = 1; /* number of clients */
...@@ -206,8 +207,8 @@ typedef struct SimpleStats ...@@ -206,8 +207,8 @@ typedef struct SimpleStats
} SimpleStats; } SimpleStats;
/* /*
* Data structure to hold various statistics: per-thread stats are maintained * Data structure to hold various statistics: per-thread and per-script stats
* and merged together. * are maintained and merged together.
*/ */
typedef struct StatsData typedef struct StatsData
{ {
...@@ -299,6 +300,7 @@ static struct ...@@ -299,6 +300,7 @@ static struct
{ {
const char *name; const char *name;
Command **commands; Command **commands;
StatsData stats;
} sql_script[MAX_SCRIPTS]; /* SQL script files */ } 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 */
...@@ -1358,7 +1360,8 @@ top: ...@@ -1358,7 +1360,8 @@ top:
/* transaction finished: calculate latency and log the transaction */ /* transaction finished: calculate latency and log the transaction */
if (commands[st->state + 1] == NULL) if (commands[st->state + 1] == NULL)
{ {
if (progress || throttle_delay || latency_limit || logfile) if (progress || throttle_delay || latency_limit ||
per_script_stats || logfile)
processXactStats(thread, st, &now, false, logfile, agg); processXactStats(thread, st, &now, false, logfile, agg);
else else
thread->stats.cnt++; thread->stats.cnt++;
...@@ -1451,7 +1454,7 @@ top: ...@@ -1451,7 +1454,7 @@ top:
} }
/* Record transaction start time under logging, progress or throttling */ /* Record transaction start time under logging, progress or throttling */
if ((logfile || progress || throttle_delay || latency_limit) && st->state == 0) if ((logfile || progress || throttle_delay || latency_limit || per_script_stats) && st->state == 0)
{ {
INSTR_TIME_SET_CURRENT(st->txn_begin); INSTR_TIME_SET_CURRENT(st->txn_begin);
...@@ -1904,6 +1907,10 @@ processXactStats(TState *thread, CState *st, instr_time *now, ...@@ -1904,6 +1907,10 @@ processXactStats(TState *thread, CState *st, instr_time *now,
if (use_log) if (use_log)
doLog(thread, st, logfile, now, agg, skipped, latency, lag); doLog(thread, st, logfile, now, agg, skipped, latency, lag);
/* XXX could use a mutex here, but we choose not to */
if (per_script_stats)
accumStats(&sql_script[st->use_file].stats, skipped, latency, lag);
} }
...@@ -2693,6 +2700,7 @@ addScript(const char *name, Command **commands) ...@@ -2693,6 +2700,7 @@ addScript(const char *name, Command **commands)
sql_script[num_scripts].name = name; sql_script[num_scripts].name = name;
sql_script[num_scripts].commands = commands; sql_script[num_scripts].commands = commands;
initStats(&sql_script[num_scripts].stats, 0.0);
num_scripts++; num_scripts++;
} }
...@@ -2776,22 +2784,43 @@ printResults(TState *threads, StatsData *total, instr_time total_time, ...@@ -2776,22 +2784,43 @@ 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 latencies */ /* Report per-command statistics */
if (is_latencies) if (per_script_stats)
{ {
int i; int i;
for (i = 0; i < num_scripts; i++) for (i = 0; i < num_scripts; i++)
{ {
Command **commands; printf("SQL script %d: %s\n"
" - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
i + 1, 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);
if (latency_limit)
printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
sql_script[i].stats.skipped,
100.0 * sql_script[i].stats.skipped /
(sql_script[i].stats.skipped + sql_script[i].stats.cnt));
printSimpleStats(" - latency", &sql_script[i].stats.latency);
printf("SQL script %d: %s\n", i + 1, sql_script[i].name); /* Report per-command latencies */
printf(" - statement latencies in milliseconds:\n"); if (is_latencies)
{
Command **commands;
printf(" - statement latencies in milliseconds:\n");
for (commands = sql_script[i].commands; *commands != NULL; commands++) for (commands = sql_script[i].commands;
printf(" %11.3f %s\n", *commands != NULL;
1000.0 * (*commands)->stats.sum / (*commands)->stats.count, commands++)
(*commands)->line); printf(" %11.3f %s\n",
1000.0 * (*commands)->stats.sum /
(*commands)->stats.count,
(*commands)->line);
}
} }
} }
} }
...@@ -2977,6 +3006,7 @@ main(int argc, char **argv) ...@@ -2977,6 +3006,7 @@ main(int argc, char **argv)
break; break;
case 'r': case 'r':
benchmarking_option_set = true; benchmarking_option_set = true;
per_script_stats = true;
is_latencies = true; is_latencies = true;
break; break;
case 's': case 's':
...@@ -3200,6 +3230,10 @@ main(int argc, char **argv) ...@@ -3200,6 +3230,10 @@ main(int argc, char **argv)
internal_script_used = true; internal_script_used = true;
} }
/* show per script stats if several scripts are used */
if (num_scripts > 1)
per_script_stats = true;
/* /*
* Don't need more threads than there are clients. (This is not merely an * Don't need more threads than there are clients. (This is not merely an
* optimization; throttle_delay is calculated incorrectly below if some * optimization; throttle_delay is calculated incorrectly below if some
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment