Skip to content

Commit 84f0ea3

Browse files
committed
Refactor pgbench log-writing code to a separate function.
The doCustom function was incredibly long, this makes it a little bit more readable.
1 parent 5a6c168 commit 84f0ea3

File tree

1 file changed

+169
-171
lines changed

1 file changed

+169
-171
lines changed

contrib/pgbench/pgbench.c

Lines changed: 169 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ static char *select_only = {
347347
static void setalarm(int seconds);
348348
static void *threadRun(void *arg);
349349

350+
static void doLog(TState *thread, CState *st, FILE *logfile, instr_time *now,
351+
AggVals *agg);
352+
350353
static void
351354
usage(void)
352355
{
@@ -1016,6 +1019,16 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
10161019
PGresult *res;
10171020
Command **commands;
10181021
bool trans_needs_throttle = false;
1022+
instr_time now;
1023+
1024+
/*
1025+
* gettimeofday() isn't free, so we get the current timestamp lazily the
1026+
* first time it's needed, and reuse the same value throughout this
1027+
* function after that. This also ensures that e.g. the calculated latency
1028+
* reported in the log file and in the totals are the same. Zero means
1029+
* "not set yet".
1030+
*/
1031+
INSTR_TIME_SET_ZERO(now);
10191032

10201033
top:
10211034
commands = sql_files[st->use_file];
@@ -1049,10 +1062,10 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
10491062

10501063
if (st->sleeping)
10511064
{ /* are we sleeping? */
1052-
instr_time now;
10531065
int64 now_us;
10541066

1055-
INSTR_TIME_SET_CURRENT(now);
1067+
if (INSTR_TIME_IS_ZERO(now))
1068+
INSTR_TIME_SET_CURRENT(now);
10561069
now_us = INSTR_TIME_GET_MICROSEC(now);
10571070
if (st->txn_scheduled <= now_us)
10581071
{
@@ -1074,11 +1087,6 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
10741087

10751088
if (st->listen)
10761089
{ /* are we receiver? */
1077-
instr_time now;
1078-
bool now_valid = false;
1079-
1080-
INSTR_TIME_SET_ZERO(now); /* initialize to keep compiler quiet */
1081-
10821090
if (commands[st->state]->type == SQL_COMMAND)
10831091
{
10841092
if (debug)
@@ -1100,181 +1108,40 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
11001108
{
11011109
int cnum = commands[st->state]->command_num;
11021110

1103-
if (!now_valid)
1104-
{
1111+
if (INSTR_TIME_IS_ZERO(now))
11051112
INSTR_TIME_SET_CURRENT(now);
1106-
now_valid = true;
1107-
}
11081113
INSTR_TIME_ACCUM_DIFF(thread->exec_elapsed[cnum],
11091114
now, st->stmt_begin);
11101115
thread->exec_count[cnum]++;
11111116
}
11121117

1113-
/* transaction finished: record latency under progress or throttling */
1114-
if ((progress || throttle_delay) && commands[st->state + 1] == NULL)
1118+
/* transaction finished: calculate latency and log the transaction */
1119+
if (commands[st->state + 1] == NULL)
11151120
{
1116-
int64 latency;
1117-
1118-
if (!now_valid)
1121+
/* only calculate latency if an option is used that needs it */
1122+
if (progress || throttle_delay)
11191123
{
1120-
INSTR_TIME_SET_CURRENT(now);
1121-
now_valid = true;
1122-
}
1123-
1124-
latency = INSTR_TIME_GET_MICROSEC(now) - st->txn_scheduled;
1124+
int64 latency;
11251125

1126-
st->txn_latencies += latency;
1127-
1128-
/*
1129-
* XXX In a long benchmark run of high-latency transactions, this
1130-
* int64 addition eventually overflows. For example, 100 threads
1131-
* running 10s transactions will overflow it in 2.56 hours. With
1132-
* a more-typical OLTP workload of .1s transactions, overflow
1133-
* would take 256 hours.
1134-
*/
1135-
st->txn_sqlats += latency * latency;
1136-
}
1137-
1138-
/*
1139-
* if transaction finished, record the time it took in the log
1140-
*/
1141-
if (logfile && commands[st->state + 1] == NULL)
1142-
{
1143-
double lag;
1144-
double latency;
1145-
1146-
/*
1147-
* write the log entry if this row belongs to the random sample,
1148-
* or no sampling rate was given which means log everything.
1149-
*/
1150-
if (sample_rate == 0.0 ||
1151-
pg_erand48(thread->random_state) <= sample_rate)
1152-
{
1153-
if (!now_valid)
1154-
{
1126+
if (INSTR_TIME_IS_ZERO(now))
11551127
INSTR_TIME_SET_CURRENT(now);
1156-
now_valid = true;
1157-
}
1158-
latency = (double) (INSTR_TIME_GET_MICROSEC(now) - st->txn_scheduled);
1159-
lag = (double) (INSTR_TIME_GET_MICROSEC(st->txn_begin) - st->txn_scheduled);
1160-
1161-
/* should we aggregate the results or not? */
1162-
if (agg_interval > 0)
1163-
{
1164-
/*
1165-
* are we still in the same interval? if yes, accumulate
1166-
* the values (print them otherwise)
1167-
*/
1168-
if (agg->start_time + agg_interval >= INSTR_TIME_GET_DOUBLE(now))
1169-
{
1170-
agg->cnt += 1;
1171-
agg->sum_latency += latency;
1172-
agg->sum2_latency += latency * latency;
1173-
1174-
/* first in this aggregation interval */
1175-
if ((agg->cnt == 1) || (latency < agg->min_latency))
1176-
agg->min_latency = latency;
1177-
1178-
if ((agg->cnt == 1) || (latency > agg->max_latency))
1179-
agg->max_latency = latency;
1180-
1181-
/* and the same for schedule lag */
1182-
if (throttle_delay)
1183-
{
1184-
agg->sum_lag += lag;
1185-
agg->sum2_lag += lag * lag;
1186-
1187-
if ((agg->cnt == 1) || (lag < agg->min_lag))
1188-
agg->min_lag = lag;
1189-
if ((agg->cnt == 1) || (lag > agg->max_lag))
1190-
agg->max_lag = lag;
1191-
}
1192-
}
1193-
else
1194-
{
1195-
/*
1196-
* Loop until we reach the interval of the current
1197-
* transaction (and print all the empty intervals in
1198-
* between).
1199-
*/
1200-
while (agg->start_time + agg_interval < INSTR_TIME_GET_DOUBLE(now))
1201-
{
1202-
/*
1203-
* This is a non-Windows branch (thanks to the
1204-
* ifdef in usage), so we don't need to handle
1205-
* this in a special way (see below).
1206-
*/
1207-
fprintf(logfile, "%ld %d %.0f %.0f %.0f %.0f",
1208-
agg->start_time,
1209-
agg->cnt,
1210-
agg->sum_latency,
1211-
agg->sum2_latency,
1212-
agg->min_latency,
1213-
agg->max_latency);
1214-
if (throttle_delay)
1215-
fprintf(logfile, " %.0f %.0f %.0f %.0f",
1216-
agg->sum_lag,
1217-
agg->sum2_lag,
1218-
agg->min_lag,
1219-
agg->max_lag);
1220-
fputc('\n', logfile);
1221-
1222-
/* move to the next inteval */
1223-
agg->start_time = agg->start_time + agg_interval;
1224-
1225-
/* reset for "no transaction" intervals */
1226-
agg->cnt = 0;
1227-
agg->min_latency = 0;
1228-
agg->max_latency = 0;
1229-
agg->sum_latency = 0;
1230-
agg->sum2_latency = 0;
1231-
agg->min_lag = 0;
1232-
agg->max_lag = 0;
1233-
agg->sum_lag = 0;
1234-
agg->sum2_lag = 0;
1235-
}
1236-
1237-
/*
1238-
* and now update the reset values (include the
1239-
* current)
1240-
*/
1241-
agg->cnt = 1;
1242-
agg->min_latency = latency;
1243-
agg->max_latency = latency;
1244-
agg->sum_latency = latency;
1245-
agg->sum2_latency = latency * latency;
1246-
agg->min_lag = lag;
1247-
agg->max_lag = lag;
1248-
agg->sum_lag = lag;
1249-
agg->sum2_lag = lag * lag;
1250-
}
1251-
}
1252-
else
1253-
{
1254-
/* no, print raw transactions */
1255-
#ifndef WIN32
1256-
1257-
/*
1258-
* This is more than we really ought to know about
1259-
* instr_time
1260-
*/
1261-
fprintf(logfile, "%d %d %.0f %d %ld %ld",
1262-
st->id, st->cnt, latency, st->use_file,
1263-
(long) now.tv_sec, (long) now.tv_usec);
1264-
#else
1265-
1266-
/*
1267-
* On Windows, instr_time doesn't provide a timestamp
1268-
* anyway
1269-
*/
1270-
fprintf(logfile, "%d %d %.0f %d 0 0",
1271-
st->id, st->cnt, latency, st->use_file);
1272-
#endif
1273-
if (throttle_delay)
1274-
fprintf(logfile, " %.0f", lag);
1275-
fputc('\n', logfile);
1276-
}
1128+
latency = INSTR_TIME_GET_MICROSEC(now) - st->txn_scheduled;
1129+
1130+
st->txn_latencies += latency;
1131+
1132+
/*
1133+
* XXX In a long benchmark run of high-latency transactions,
1134+
* this int64 addition eventually overflows. For example, 100
1135+
* threads running 10s transactions will overflow it in 2.56
1136+
* hours. With a more-typical OLTP workload of .1s
1137+
* transactions, overflow would take 256 hours.
1138+
*/
1139+
st->txn_sqlats += latency * latency;
12771140
}
1141+
1142+
/* record the time it took in the log */
1143+
if (logfile)
1144+
doLog(thread, st, logfile, &now, agg);
12781145
}
12791146

12801147
if (commands[st->state]->type == SQL_COMMAND)
@@ -1734,6 +1601,137 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
17341601
return true;
17351602
}
17361603

1604+
/*
1605+
* print log entry after completing one transaction.
1606+
*/
1607+
static void
1608+
doLog(TState *thread, CState *st, FILE *logfile, instr_time *now, AggVals *agg)
1609+
{
1610+
double lag;
1611+
double latency;
1612+
1613+
/*
1614+
* Skip the log entry if sampling is enabled and this row doesn't belong
1615+
* to the random sample.
1616+
*/
1617+
if (sample_rate != 0.0 &&
1618+
pg_erand48(thread->random_state) > sample_rate)
1619+
return;
1620+
1621+
if (INSTR_TIME_IS_ZERO(*now))
1622+
INSTR_TIME_SET_CURRENT(*now);
1623+
1624+
latency = (double) (INSTR_TIME_GET_MICROSEC(*now) - st->txn_scheduled);
1625+
lag = (double) (INSTR_TIME_GET_MICROSEC(st->txn_begin) - st->txn_scheduled);
1626+
1627+
/* should we aggregate the results or not? */
1628+
if (agg_interval > 0)
1629+
{
1630+
/*
1631+
* Are we still in the same interval? If yes, accumulate the values
1632+
* (print them otherwise)
1633+
*/
1634+
if (agg->start_time + agg_interval >= INSTR_TIME_GET_DOUBLE(*now))
1635+
{
1636+
agg->cnt += 1;
1637+
agg->sum_latency += latency;
1638+
agg->sum2_latency += latency * latency;
1639+
1640+
/* first in this aggregation interval */
1641+
if ((agg->cnt == 1) || (latency < agg->min_latency))
1642+
agg->min_latency = latency;
1643+
1644+
if ((agg->cnt == 1) || (latency > agg->max_latency))
1645+
agg->max_latency = latency;
1646+
1647+
/* and the same for schedule lag */
1648+
if (throttle_delay)
1649+
{
1650+
agg->sum_lag += lag;
1651+
agg->sum2_lag += lag * lag;
1652+
1653+
if ((agg->cnt == 1) || (lag < agg->min_lag))
1654+
agg->min_lag = lag;
1655+
if ((agg->cnt == 1) || (lag > agg->max_lag))
1656+
agg->max_lag = lag;
1657+
}
1658+
}
1659+
else
1660+
{
1661+
/*
1662+
* Loop until we reach the interval of the current transaction
1663+
* (and print all the empty intervals in between).
1664+
*/
1665+
while (agg->start_time + agg_interval < INSTR_TIME_GET_DOUBLE(*now))
1666+
{
1667+
/*
1668+
* This is a non-Windows branch (thanks to the
1669+
* ifdef in usage), so we don't need to handle
1670+
* this in a special way (see below).
1671+
*/
1672+
fprintf(logfile, "%ld %d %.0f %.0f %.0f %.0f",
1673+
agg->start_time,
1674+
agg->cnt,
1675+
agg->sum_latency,
1676+
agg->sum2_latency,
1677+
agg->min_latency,
1678+
agg->max_latency);
1679+
if (throttle_delay)
1680+
fprintf(logfile, " %.0f %.0f %.0f %.0f",
1681+
agg->sum_lag,
1682+
agg->sum2_lag,
1683+
agg->min_lag,
1684+
agg->max_lag);
1685+
fputc('\n', logfile);
1686+
1687+
/* move to the next inteval */
1688+
agg->start_time = agg->start_time + agg_interval;
1689+
1690+
/* reset for "no transaction" intervals */
1691+
agg->cnt = 0;
1692+
agg->min_latency = 0;
1693+
agg->max_latency = 0;
1694+
agg->sum_latency = 0;
1695+
agg->sum2_latency = 0;
1696+
agg->min_lag = 0;
1697+
agg->max_lag = 0;
1698+
agg->sum_lag = 0;
1699+
agg->sum2_lag = 0;
1700+
}
1701+
1702+
/* reset the values to include only the current transaction. */
1703+
agg->cnt = 1;
1704+
agg->min_latency = latency;
1705+
agg->max_latency = latency;
1706+
agg->sum_latency = latency;
1707+
agg->sum2_latency = latency * latency;
1708+
agg->min_lag = lag;
1709+
agg->max_lag = lag;
1710+
agg->sum_lag = lag;
1711+
agg->sum2_lag = lag * lag;
1712+
}
1713+
}
1714+
else
1715+
{
1716+
/* no, print raw transactions */
1717+
#ifndef WIN32
1718+
1719+
/* This is more than we really ought to know about instr_time */
1720+
fprintf(logfile, "%d %d %.0f %d %ld %ld",
1721+
st->id, st->cnt, latency, st->use_file,
1722+
(long) now->tv_sec, (long) now->tv_usec);
1723+
#else
1724+
1725+
/* On Windows, instr_time doesn't provide a timestamp anyway */
1726+
fprintf(logfile, "%d %d %.0f %d 0 0",
1727+
st->id, st->cnt, latency, st->use_file);
1728+
#endif
1729+
if (throttle_delay)
1730+
fprintf(logfile, " %.0f", lag);
1731+
fputc('\n', logfile);
1732+
}
1733+
}
1734+
17371735
/* discard connections */
17381736
static void
17391737
disconnect_all(CState *state, int length)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy