@@ -204,10 +204,10 @@ typedef struct
204
204
* sent */
205
205
int sleeping ; /* 1 indicates that the client is napping */
206
206
bool throttling ; /* whether nap is for throttling */
207
- int64 until ; /* napping until (usec) */
208
207
Variable * variables ; /* array of variable definitions */
209
208
int nvariables ;
210
- instr_time txn_begin ; /* used for measuring transaction latencies */
209
+ int64 txn_scheduled ; /* scheduled start time of transaction (usec) */
210
+ instr_time txn_begin ; /* used for measuring schedule lag times */
211
211
instr_time stmt_begin ; /* used for measuring statement latencies */
212
212
int64 txn_latencies ; /* cumulated latencies */
213
213
int64 txn_sqlats ; /* cumulated square latencies */
@@ -278,12 +278,17 @@ typedef struct
278
278
279
279
long start_time ; /* when does the interval start */
280
280
int cnt ; /* number of transactions */
281
- double min_duration ; /* min/max durations */
282
- double max_duration ;
283
- double sum ; /* sum(duration), sum(duration^2) - for
281
+
282
+ double min_latency ; /* min/max latencies */
283
+ double max_latency ;
284
+ double sum_latency ; /* sum(latency), sum(latency^2) - for
284
285
* estimates */
285
- double sum2 ;
286
+ double sum2_latency ;
286
287
288
+ double min_lag ;
289
+ double max_lag ;
290
+ double sum_lag ; /* sum(lag) */
291
+ double sum2_lag ; /* sum(lag*lag) */
287
292
} AggVals ;
288
293
289
294
static Command * * sql_files [MAX_FILES ]; /* SQL script files */
@@ -892,12 +897,18 @@ agg_vals_init(AggVals *aggs, instr_time start)
892
897
{
893
898
/* basic counters */
894
899
aggs -> cnt = 0 ; /* number of transactions */
895
- aggs -> sum = 0 ; /* SUM(duration ) */
896
- aggs -> sum2 = 0 ; /* SUM(duration*duration ) */
900
+ aggs -> sum_latency = 0 ; /* SUM(latency ) */
901
+ aggs -> sum2_latency = 0 ; /* SUM(latency*latency ) */
897
902
898
903
/* min and max transaction duration */
899
- aggs -> min_duration = 0 ;
900
- aggs -> max_duration = 0 ;
904
+ aggs -> min_latency = 0 ;
905
+ aggs -> max_latency = 0 ;
906
+
907
+ /* schedule lag counters */
908
+ aggs -> sum_lag = 0 ;
909
+ aggs -> sum2_lag = 0 ;
910
+ aggs -> min_lag = 0 ;
911
+ aggs -> max_lag = 0 ;
901
912
902
913
/* start of the current interval */
903
914
aggs -> start_time = INSTR_TIME_GET_DOUBLE (start );
@@ -940,7 +951,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
940
951
941
952
thread -> throttle_trigger += wait ;
942
953
943
- st -> until = thread -> throttle_trigger ;
954
+ st -> txn_scheduled = thread -> throttle_trigger ;
944
955
st -> sleeping = 1 ;
945
956
st -> throttling = true;
946
957
st -> is_throttled = true;
@@ -956,13 +967,13 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
956
967
957
968
INSTR_TIME_SET_CURRENT (now );
958
969
now_us = INSTR_TIME_GET_MICROSEC (now );
959
- if (st -> until <= now_us )
970
+ if (st -> txn_scheduled <= now_us )
960
971
{
961
972
st -> sleeping = 0 ; /* Done sleeping, go ahead with next command */
962
973
if (st -> throttling )
963
974
{
964
975
/* Measure lag of throttled transaction relative to target */
965
- int64 lag = now_us - st -> until ;
976
+ int64 lag = now_us - st -> txn_scheduled ;
966
977
967
978
thread -> throttle_lag += lag ;
968
979
if (lag > thread -> throttle_lag_max )
@@ -976,6 +987,11 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
976
987
977
988
if (st -> listen )
978
989
{ /* are we receiver? */
990
+ instr_time now ;
991
+ bool now_valid = false;
992
+
993
+ INSTR_TIME_SET_ZERO (now ); /* initialize to keep compiler quiet */
994
+
979
995
if (commands [st -> state ]-> type == SQL_COMMAND )
980
996
{
981
997
if (debug )
@@ -995,10 +1011,13 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
995
1011
*/
996
1012
if (is_latencies )
997
1013
{
998
- instr_time now ;
999
1014
int cnum = commands [st -> state ]-> command_num ;
1000
1015
1001
- INSTR_TIME_SET_CURRENT (now );
1016
+ if (!now_valid )
1017
+ {
1018
+ INSTR_TIME_SET_CURRENT (now );
1019
+ now_valid = true;
1020
+ }
1002
1021
INSTR_TIME_ACCUM_DIFF (thread -> exec_elapsed [cnum ],
1003
1022
now , st -> stmt_begin );
1004
1023
thread -> exec_count [cnum ]++ ;
@@ -1007,12 +1026,16 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1007
1026
/* transaction finished: record latency under progress or throttling */
1008
1027
if ((progress || throttle_delay ) && commands [st -> state + 1 ] == NULL )
1009
1028
{
1010
- instr_time diff ;
1011
1029
int64 latency ;
1012
1030
1013
- INSTR_TIME_SET_CURRENT (diff );
1014
- INSTR_TIME_SUBTRACT (diff , st -> txn_begin );
1015
- latency = INSTR_TIME_GET_MICROSEC (diff );
1031
+ if (!now_valid )
1032
+ {
1033
+ INSTR_TIME_SET_CURRENT (now );
1034
+ now_valid = true;
1035
+ }
1036
+
1037
+ latency = INSTR_TIME_GET_MICROSEC (now ) - st -> txn_scheduled ;
1038
+
1016
1039
st -> txn_latencies += latency ;
1017
1040
1018
1041
/*
@@ -1030,9 +1053,8 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1030
1053
*/
1031
1054
if (logfile && commands [st -> state + 1 ] == NULL )
1032
1055
{
1033
- instr_time now ;
1034
- instr_time diff ;
1035
- double usec ;
1056
+ double lag ;
1057
+ double latency ;
1036
1058
1037
1059
/*
1038
1060
* write the log entry if this row belongs to the random sample,
@@ -1041,10 +1063,13 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1041
1063
if (sample_rate == 0.0 ||
1042
1064
pg_erand48 (thread -> random_state ) <= sample_rate )
1043
1065
{
1044
- INSTR_TIME_SET_CURRENT (now );
1045
- diff = now ;
1046
- INSTR_TIME_SUBTRACT (diff , st -> txn_begin );
1047
- usec = (double ) INSTR_TIME_GET_MICROSEC (diff );
1066
+ if (!now_valid )
1067
+ {
1068
+ INSTR_TIME_SET_CURRENT (now );
1069
+ now_valid = true;
1070
+ }
1071
+ latency = (double ) (INSTR_TIME_GET_MICROSEC (now ) - st -> txn_scheduled );
1072
+ lag = (double ) (INSTR_TIME_GET_MICROSEC (st -> txn_begin ) - st -> txn_scheduled );
1048
1073
1049
1074
/* should we aggregate the results or not? */
1050
1075
if (agg_interval > 0 )
@@ -1056,15 +1081,27 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1056
1081
if (agg -> start_time + agg_interval >= INSTR_TIME_GET_DOUBLE (now ))
1057
1082
{
1058
1083
agg -> cnt += 1 ;
1059
- agg -> sum += usec ;
1060
- agg -> sum2 += usec * usec ;
1084
+ agg -> sum_latency += latency ;
1085
+ agg -> sum2_latency += latency * latency ;
1061
1086
1062
1087
/* first in this aggregation interval */
1063
- if ((agg -> cnt == 1 ) || (usec < agg -> min_duration ))
1064
- agg -> min_duration = usec ;
1088
+ if ((agg -> cnt == 1 ) || (latency < agg -> min_latency ))
1089
+ agg -> min_latency = latency ;
1090
+
1091
+ if ((agg -> cnt == 1 ) || (latency > agg -> max_latency ))
1092
+ agg -> max_latency = latency ;
1093
+
1094
+ /* and the same for schedule lag */
1095
+ if (throttle_delay )
1096
+ {
1097
+ agg -> sum_lag += lag ;
1098
+ agg -> sum2_lag += lag * lag ;
1065
1099
1066
- if ((agg -> cnt == 1 ) || (usec > agg -> max_duration ))
1067
- agg -> max_duration = usec ;
1100
+ if ((agg -> cnt == 1 ) || (lag < agg -> min_lag ))
1101
+ agg -> min_lag = lag ;
1102
+ if ((agg -> cnt == 1 ) || (lag > agg -> max_lag ))
1103
+ agg -> max_lag = lag ;
1104
+ }
1068
1105
}
1069
1106
else
1070
1107
{
@@ -1080,34 +1117,49 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1080
1117
* ifdef in usage), so we don't need to handle
1081
1118
* this in a special way (see below).
1082
1119
*/
1083
- fprintf (logfile , "%ld %d %.0f %.0f %.0f %.0f\n " ,
1120
+ fprintf (logfile , "%ld %d %.0f %.0f %.0f %.0f" ,
1084
1121
agg -> start_time ,
1085
1122
agg -> cnt ,
1086
- agg -> sum ,
1087
- agg -> sum2 ,
1088
- agg -> min_duration ,
1089
- agg -> max_duration );
1123
+ agg -> sum_latency ,
1124
+ agg -> sum2_latency ,
1125
+ agg -> min_latency ,
1126
+ agg -> max_latency );
1127
+ if (throttle_delay )
1128
+ fprintf (logfile , " %.0f %.0f %.0f %.0f" ,
1129
+ agg -> sum_lag ,
1130
+ agg -> sum2_lag ,
1131
+ agg -> min_lag ,
1132
+ agg -> max_lag );
1133
+ fputc ('\n' , logfile );
1090
1134
1091
1135
/* move to the next inteval */
1092
1136
agg -> start_time = agg -> start_time + agg_interval ;
1093
1137
1094
1138
/* reset for "no transaction" intervals */
1095
1139
agg -> cnt = 0 ;
1096
- agg -> min_duration = 0 ;
1097
- agg -> max_duration = 0 ;
1098
- agg -> sum = 0 ;
1099
- agg -> sum2 = 0 ;
1140
+ agg -> min_latency = 0 ;
1141
+ agg -> max_latency = 0 ;
1142
+ agg -> sum_latency = 0 ;
1143
+ agg -> sum2_latency = 0 ;
1144
+ agg -> min_lag = 0 ;
1145
+ agg -> max_lag = 0 ;
1146
+ agg -> sum_lag = 0 ;
1147
+ agg -> sum2_lag = 0 ;
1100
1148
}
1101
1149
1102
1150
/*
1103
1151
* and now update the reset values (include the
1104
1152
* current)
1105
1153
*/
1106
1154
agg -> cnt = 1 ;
1107
- agg -> min_duration = usec ;
1108
- agg -> max_duration = usec ;
1109
- agg -> sum = usec ;
1110
- agg -> sum2 = usec * usec ;
1155
+ agg -> min_latency = latency ;
1156
+ agg -> max_latency = latency ;
1157
+ agg -> sum_latency = latency ;
1158
+ agg -> sum2_latency = latency * latency ;
1159
+ agg -> min_lag = lag ;
1160
+ agg -> max_lag = lag ;
1161
+ agg -> sum_lag = lag ;
1162
+ agg -> sum2_lag = lag * lag ;
1111
1163
}
1112
1164
}
1113
1165
else
@@ -1119,18 +1171,21 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1119
1171
* This is more than we really ought to know about
1120
1172
* instr_time
1121
1173
*/
1122
- fprintf (logfile , "%d %d %.0f %d %ld %ld\n " ,
1123
- st -> id , st -> cnt , usec , st -> use_file ,
1174
+ fprintf (logfile , "%d %d %.0f %d %ld %ld" ,
1175
+ st -> id , st -> cnt , latency , st -> use_file ,
1124
1176
(long ) now .tv_sec , (long ) now .tv_usec );
1125
1177
#else
1126
1178
1127
1179
/*
1128
1180
* On Windows, instr_time doesn't provide a timestamp
1129
1181
* anyway
1130
1182
*/
1131
- fprintf (logfile , "%d %d %.0f %d 0 0\n " ,
1183
+ fprintf (logfile , "%d %d %.0f %d 0 0" ,
1132
1184
st -> id , st -> cnt , usec , st -> use_file );
1133
1185
#endif
1186
+ if (throttle_delay )
1187
+ fprintf (logfile , " %.0f" , lag );
1188
+ fputc ('\n' , logfile );
1134
1189
}
1135
1190
}
1136
1191
}
@@ -1219,8 +1274,17 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1219
1274
1220
1275
/* Record transaction start time under logging, progress or throttling */
1221
1276
if ((logfile || progress || throttle_delay ) && st -> state == 0 )
1277
+ {
1222
1278
INSTR_TIME_SET_CURRENT (st -> txn_begin );
1223
1279
1280
+ /*
1281
+ * When not throttling, this is also the transaction's scheduled start
1282
+ * time.
1283
+ */
1284
+ if (!throttle_delay )
1285
+ st -> txn_scheduled = INSTR_TIME_GET_MICROSEC (st -> txn_begin );
1286
+ }
1287
+
1224
1288
/* Record statement start time if per-command latencies are requested */
1225
1289
if (is_latencies )
1226
1290
INSTR_TIME_SET_CURRENT (st -> stmt_begin );
@@ -1489,7 +1553,7 @@ doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile, AggVa
1489
1553
usec *= 1000000 ;
1490
1554
1491
1555
INSTR_TIME_SET_CURRENT (now );
1492
- st -> until = INSTR_TIME_GET_MICROSEC (now ) + usec ;
1556
+ st -> txn_scheduled = INSTR_TIME_GET_MICROSEC (now ) + usec ;
1493
1557
st -> sleeping = 1 ;
1494
1558
1495
1559
st -> listen = 1 ;
@@ -3108,7 +3172,7 @@ threadRun(void *arg)
3108
3172
now_usec = INSTR_TIME_GET_MICROSEC (now );
3109
3173
}
3110
3174
3111
- this_usec = st -> until - now_usec ;
3175
+ this_usec = st -> txn_scheduled - now_usec ;
3112
3176
if (min_usec > this_usec )
3113
3177
min_usec = this_usec ;
3114
3178
}
0 commit comments