mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
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
This commit is contained in:
@ -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 */
|
|||||||
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
|
|||||||
} 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
|
|||||||
{
|
{
|
||||||
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:
|
|||||||
/* 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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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);
|
||||||
|
|
||||||
printf("SQL script %d: %s\n", i + 1, sql_script[i].name);
|
if (latency_limit)
|
||||||
printf(" - statement latencies in milliseconds:\n");
|
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));
|
||||||
|
|
||||||
for (commands = sql_script[i].commands; *commands != NULL; commands++)
|
printSimpleStats(" - latency", &sql_script[i].stats.latency);
|
||||||
printf(" %11.3f %s\n",
|
|
||||||
1000.0 * (*commands)->stats.sum / (*commands)->stats.count,
|
/* Report per-command latencies */
|
||||||
(*commands)->line);
|
if (is_latencies)
|
||||||
|
{
|
||||||
|
Command **commands;
|
||||||
|
|
||||||
|
printf(" - statement latencies in milliseconds:\n");
|
||||||
|
|
||||||
|
for (commands = sql_script[i].commands;
|
||||||
|
*commands != NULL;
|
||||||
|
commands++)
|
||||||
|
printf(" %11.3f %s\n",
|
||||||
|
1000.0 * (*commands)->stats.sum /
|
||||||
|
(*commands)->stats.count,
|
||||||
|
(*commands)->line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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)
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user