1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

pgbench: Elaborate latency reporting.

Isolate transaction latency (elapsed time between submitting first
command and receiving response to last command) from client-side delays
pertaining to the --rate schedule.  Under --rate, report schedule lag as
defined in the documentation.  Report latency standard deviation
whenever we collect the measurements to do so.  All of these changes
affect --progress messages and the final report.

Fabien COELHO, reviewed by Pavel Stehule.
This commit is contained in:
Noah Misch
2013-10-05 17:33:38 -04:00
parent 8e00a3850d
commit 2d6c0f10ef
2 changed files with 115 additions and 18 deletions

View File

@ -172,6 +172,7 @@ int agg_interval; /* log aggregates instead of individual
* transactions */
int progress = 0; /* thread progress report every this seconds */
int progress_nclients = 0; /* number of clients for progress report */
int progress_nthreads = 0; /* number of threads for progress report */
bool is_connect; /* establish connection for each transaction */
bool is_latencies; /* report per-command latencies */
int main_pid; /* main process id used in log filename */
@ -214,6 +215,8 @@ typedef struct
int nvariables;
instr_time txn_begin; /* used for measuring transaction latencies */
instr_time stmt_begin; /* used for measuring statement latencies */
int64 txn_latencies; /* cumulated latencies */
int64 txn_sqlats; /* cumulated square latencies */
bool is_throttled; /* whether transaction throttling is done */
int use_file; /* index in sql_files for this client */
bool prepared[MAX_FILES];
@ -243,6 +246,8 @@ typedef struct
{
instr_time conn_time;
int xacts;
int64 latencies;
int64 sqlats;
int64 throttle_lag;
int64 throttle_lag_max;
} TResult;
@ -1006,6 +1011,26 @@ top:
thread->exec_count[cnum]++;
}
/* transaction finished: record latency under progress or throttling */
if ((progress || throttle_delay) && commands[st->state + 1] == NULL)
{
instr_time diff;
int64 latency;
INSTR_TIME_SET_CURRENT(diff);
INSTR_TIME_SUBTRACT(diff, st->txn_begin);
latency = INSTR_TIME_GET_MICROSEC(diff);
st->txn_latencies += latency;
/*
* XXX In a long benchmark run of high-latency transactions, this
* int64 addition eventually overflows. For example, 100 threads
* running 10s transactions will overflow it in 2.56 hours. With
* a more-typical OLTP workload of .1s transactions, overflow
* would take 256 hours.
*/
st->txn_sqlats += latency * latency;
}
/*
* if transaction finished, record the time it took in the log
*/
@ -1195,8 +1220,8 @@ top:
goto top;
}
/* Record transaction start time if logging is enabled */
if (logfile && st->state == 0)
/* Record transaction start time under logging, progress or throttling */
if ((logfile || progress || throttle_delay) && st->state == 0)
INSTR_TIME_SET_CURRENT(st->txn_begin);
/* Record statement start time if per-command latencies are requested */
@ -2105,6 +2130,7 @@ static void
printResults(int ttype, int normal_xacts, int nclients,
TState *threads, int nthreads,
instr_time total_time, instr_time conn_total_time,
int64 total_latencies, int64 total_sqlats,
int64 throttle_lag, int64 throttle_lag_max)
{
double time_include,
@ -2144,6 +2170,22 @@ printResults(int ttype, int normal_xacts, int nclients,
normal_xacts);
}
if (throttle_delay || progress)
{
/* compute and show latency average and standard deviation */
double latency = 0.001 * total_latencies / normal_xacts;
double sqlat = (double) total_sqlats / normal_xacts;
printf("latency average: %.3f ms\n"
"latency stddev: %.3f ms\n",
latency, 0.001 * sqrt(sqlat - 1000000.0 * latency * latency));
}
else
{
/* only an average latency computed from the duration is available */
printf("latency average: %.3f ms\n",
1000.0 * duration * nclients / normal_xacts);
}
if (throttle_delay)
{
/*
@ -2152,7 +2194,7 @@ printResults(int ttype, int normal_xacts, int nclients,
* transaction. The measured lag may be caused by thread/client load,
* the database load, or the Poisson throttling process.
*/
printf("average rate limit schedule lag: %.3f ms (max %.3f ms)\n",
printf("rate limit schedule lag: avg %.3f (max %.3f) ms\n",
0.001 * throttle_lag / normal_xacts, 0.001 * throttle_lag_max);
}
@ -2263,7 +2305,9 @@ main(int argc, char **argv)
instr_time start_time; /* start up time */
instr_time total_time;
instr_time conn_total_time;
int total_xacts;
int total_xacts = 0;
int64 total_latencies = 0;
int64 total_sqlats = 0;
int64 throttle_lag = 0;
int64 throttle_lag_max = 0;
@ -2617,6 +2661,7 @@ main(int argc, char **argv)
*/
main_pid = (int) getpid();
progress_nclients = nclients;
progress_nthreads = nthreads;
if (nclients > 1)
{
@ -2825,7 +2870,6 @@ main(int argc, char **argv)
}
/* wait for threads and accumulate results */
total_xacts = 0;
INSTR_TIME_SET_ZERO(conn_total_time);
for (i = 0; i < nthreads; i++)
{
@ -2841,6 +2885,8 @@ main(int argc, char **argv)
TResult *r = (TResult *) ret;
total_xacts += r->xacts;
total_latencies += r->latencies;
total_sqlats += r->sqlats;
throttle_lag += r->throttle_lag;
if (r->throttle_lag_max > throttle_lag_max)
throttle_lag_max = r->throttle_lag_max;
@ -2854,7 +2900,8 @@ main(int argc, char **argv)
INSTR_TIME_SET_CURRENT(total_time);
INSTR_TIME_SUBTRACT(total_time, start_time);
printResults(ttype, total_xacts, nclients, threads, nthreads,
total_time, conn_total_time, throttle_lag, throttle_lag_max);
total_time, conn_total_time, total_latencies, total_sqlats,
throttle_lag, throttle_lag_max);
return 0;
}
@ -2875,7 +2922,7 @@ threadRun(void *arg)
int64 thread_start = INSTR_TIME_GET_MICROSEC(thread->start_time);
int64 last_report = thread_start;
int64 next_report = last_report + progress * 1000000;
int64 last_count = 0;
int64 last_count = 0, last_lats = 0, last_sqlats = 0, last_lags = 0;
AggVals aggs;
@ -3075,21 +3122,40 @@ threadRun(void *arg)
if (now >= next_report)
{
/* generate and show report */
int64 count = 0;
int64 count = 0, lats = 0, sqlats = 0;
int64 lags = thread->throttle_lag;
int64 run = now - last_report;
double tps, total_run, latency;
double tps, total_run, latency, sqlat, stdev, lag;
for (i = 0 ; i < nstate ; i++)
{
count += state[i].cnt;
lats += state[i].txn_latencies;
sqlats += state[i].txn_sqlats;
}
total_run = (now - thread_start) / 1000000.0;
tps = 1000000.0 * (count - last_count) / run;
latency = 1000.0 * nstate / tps;
latency = 0.001 * (lats - last_lats) / (count - last_count);
sqlat = 1.0 * (sqlats - last_sqlats) / (count - last_count);
stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
lag = 0.001 * (lags - last_lags) / (count - last_count);
fprintf(stderr, "progress %d: %.1f s, %.1f tps, %.3f ms lat\n",
thread->tid, total_run, tps, latency);
if (throttle_delay)
fprintf(stderr,
"progress %d: %.1f s, %.1f tps, "
"lat %.3f ms stddev %.3f, lag %.3f ms\n",
thread->tid, total_run, tps, latency, stdev, lag);
else
fprintf(stderr,
"progress %d: %.1f s, %.1f tps, "
"lat %.3f ms stddev %.3f\n",
thread->tid, total_run, tps, latency, stdev);
last_count = count;
last_lats = lats;
last_sqlats = sqlats;
last_lags = lags;
last_report = now;
next_report += progress * 1000000;
}
@ -3105,21 +3171,42 @@ threadRun(void *arg)
if (now >= next_report)
{
/* generate and show report */
int64 count = 0;
int64 count = 0, lats = 0, sqlats = 0, lags = 0;
int64 run = now - last_report;
double tps, total_run, latency;
double tps, total_run, latency, sqlat, lag, stdev;
for (i = 0 ; i < progress_nclients ; i++)
{
count += state[i].cnt;
lats += state[i].txn_latencies;
sqlats += state[i].txn_sqlats;
}
for (i = 0 ; i < progress_nthreads ; i++)
lags += thread[i].throttle_lag;
total_run = (now - thread_start) / 1000000.0;
tps = 1000000.0 * (count - last_count) / run;
latency = 1000.0 * progress_nclients / tps;
latency = 0.001 * (lats - last_lats) / (count - last_count);
sqlat = 1.0 * (sqlats - last_sqlats) / (count - last_count);
stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
lag = 0.001 * (lags - last_lags) / (count - last_count);
fprintf(stderr, "progress: %.1f s, %.1f tps, %.3f ms lat\n",
total_run, tps, latency);
if (throttle_delay)
fprintf(stderr,
"progress: %.1f s, %.1f tps, "
"lat %.3f ms stddev %.3f, lag %.3f ms\n",
total_run, tps, latency, stdev, lag);
else
fprintf(stderr,
"progress: %.1f s, %.1f tps, "
"lat %.3f ms stddev %.3f\n",
total_run, tps, latency, stdev);
last_count = count;
last_lats = lats;
last_sqlats = sqlats;
last_lags = lags;
last_report = now;
next_report += progress * 1000000;
}
@ -3131,8 +3218,14 @@ done:
INSTR_TIME_SET_CURRENT(start);
disconnect_all(state, nstate);
result->xacts = 0;
result->latencies = 0;
result->sqlats = 0;
for (i = 0; i < nstate; i++)
{
result->xacts += state[i].cnt;
result->latencies += state[i].txn_latencies;
result->sqlats += state[i].txn_sqlats;
}
result->throttle_lag = thread->throttle_lag;
result->throttle_lag_max = thread->throttle_lag_max;
INSTR_TIME_SET_CURRENT(end);