Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cee5238

Browse files
committed
pg_test_timing utility, to measure clock monotonicity and timing cost.
Ants Aasma, Greg Smith
1 parent 5b4f346 commit cee5238

File tree

9 files changed

+451
-2
lines changed

9 files changed

+451
-2
lines changed

contrib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ SUBDIRS = \
3535
pg_standby \
3636
pg_stat_statements \
3737
pg_test_fsync \
38+
pg_test_timing \
3839
pg_trgm \
3940
pg_upgrade \
4041
pg_upgrade_support \

contrib/pg_test_timing/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/pg_test_timing

contrib/pg_test_timing/Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# contrib/pg_test_timing/Makefile
2+
3+
PGFILEDESC = "pg_test_timing - test timing overhead"
4+
PGAPPICON = win32
5+
6+
PROGRAM = pg_test_timing
7+
OBJS = pg_test_timing.o
8+
9+
ifdef USE_PGXS
10+
PG_CONFIG = pg_config
11+
PGXS := $(shell $(PG_CONFIG) --pgxs)
12+
include $(PGXS)
13+
else
14+
subdir = contrib/pg_test_timing
15+
top_builddir = ../..
16+
include $(top_builddir)/src/Makefile.global
17+
include $(top_srcdir)/contrib/contrib-global.mk
18+
endif
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* pg_test_timing.c
3+
* tests overhead of timing calls and their monotonicity: that
4+
* they always move forward
5+
*/
6+
7+
#include "postgres_fe.h"
8+
9+
#include "getopt_long.h"
10+
#include "portability/instr_time.h"
11+
12+
static const char *progname;
13+
14+
static int32 test_duration = 3;
15+
16+
static void handle_args(int argc, char *argv[]);
17+
static void test_timing(int32);
18+
19+
int
20+
main(int argc, char *argv[])
21+
{
22+
progname = get_progname(argv[0]);
23+
24+
handle_args(argc, argv);
25+
26+
test_timing(test_duration);
27+
28+
return 0;
29+
}
30+
31+
static void
32+
handle_args(int argc, char *argv[])
33+
{
34+
static struct option long_options[] = {
35+
{"duration", required_argument, NULL, 'd'},
36+
{NULL, 0, NULL, 0}
37+
};
38+
int option; /* Command line option */
39+
int optindex = 0; /* used by getopt_long */
40+
41+
if (argc > 1)
42+
{
43+
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
44+
strcmp(argv[1], "-?") == 0)
45+
{
46+
printf("Usage: %s [-d DURATION]\n", progname);
47+
exit(0);
48+
}
49+
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
50+
{
51+
puts("pg_test_timing (PostgreSQL) " PG_VERSION);
52+
exit(0);
53+
}
54+
}
55+
56+
while ((option = getopt_long(argc, argv, "d:",
57+
long_options, &optindex)) != -1)
58+
{
59+
switch (option)
60+
{
61+
case 'd':
62+
test_duration = atoi(optarg);
63+
break;
64+
65+
default:
66+
fprintf(stderr, "Try \"%s --help\" for more information.\n",
67+
progname);
68+
exit(1);
69+
break;
70+
}
71+
}
72+
73+
if (argc > optind)
74+
{
75+
fprintf(stderr,
76+
"%s: too many command-line arguments (first is \"%s\")\n",
77+
progname, argv[optind]);
78+
fprintf(stderr, "Try \"%s --help\" for more information.\n",
79+
progname);
80+
exit(1);
81+
}
82+
83+
if (test_duration > 0)
84+
{
85+
printf("Testing timing overhead for %d seconds.\n", test_duration);
86+
}
87+
else
88+
{
89+
fprintf(stderr,
90+
"%s: duration must be a positive integer (duration is \"%d\")\n",
91+
progname, test_duration);
92+
fprintf(stderr, "Try \"%s --help\" for more information.\n",
93+
progname);
94+
exit(1);
95+
}
96+
}
97+
98+
static void
99+
test_timing(int32 duration)
100+
{
101+
uint64 total_time;
102+
int64 time_elapsed = 0;
103+
uint64 loop_count = 0;
104+
uint64 prev, cur;
105+
int32 diff, i, bits, found;
106+
107+
instr_time start_time, end_time, temp;
108+
109+
static int64 histogram[32];
110+
111+
total_time = duration > 0 ? duration * 1000000 : 0;
112+
113+
INSTR_TIME_SET_CURRENT(start_time);
114+
cur = INSTR_TIME_GET_MICROSEC(start_time);
115+
116+
while (time_elapsed < total_time)
117+
{
118+
prev = cur;
119+
INSTR_TIME_SET_CURRENT(temp);
120+
cur = INSTR_TIME_GET_MICROSEC(temp);
121+
diff = cur - prev;
122+
123+
if (diff < 0)
124+
{
125+
printf("Detected clock going backwards in time.\n");
126+
printf("Time warp: %d microseconds\n", diff);
127+
exit(1);
128+
}
129+
130+
bits = 0;
131+
while (diff)
132+
{
133+
diff >>= 1;
134+
bits++;
135+
}
136+
histogram[bits]++;
137+
138+
loop_count++;
139+
INSTR_TIME_SUBTRACT(temp, start_time);
140+
time_elapsed = INSTR_TIME_GET_MICROSEC(temp);
141+
}
142+
143+
INSTR_TIME_SET_CURRENT(end_time);
144+
145+
INSTR_TIME_SUBTRACT(end_time, start_time);
146+
147+
printf("Per loop time including overhead: %0.2f nsec\n",
148+
INSTR_TIME_GET_DOUBLE(end_time) * 1e9 / loop_count);
149+
printf("Histogram of timing durations:\n");
150+
printf("%9s: %10s %9s\n", "< usec", "count", "percent");
151+
152+
found = 0;
153+
for (i = 31; i >= 0; i--)
154+
{
155+
if (found || histogram[i])
156+
{
157+
found = 1;
158+
printf("%9ld: %10ld %8.5f%%\n", 1l << i, histogram[i],
159+
(double) histogram[i] * 100 / loop_count);
160+
}
161+
}
162+
}

doc/src/sgml/config.sgml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4294,7 +4294,9 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
42944294
Enables timing of database I/O calls. This parameter is off by
42954295
default, because it will repeatedly query the operating system for
42964296
the current time, which may cause significant overhead on some
4297-
platforms. Only superusers can change this setting.
4297+
platforms. You can use the <xref linkend="pgtesttiming"> tool to
4298+
measure the overhead of timing on your system. Only superusers can
4299+
change this setting.
42984300
</para>
42994301
</listitem>
43004302
</varlistentry>

doc/src/sgml/contrib.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ CREATE EXTENSION <replaceable>module_name</> FROM unpackaged;
121121
&pgstatstatements;
122122
&pgstattuple;
123123
&pgtestfsync;
124+
&pgtesttiming;
124125
&pgtrgm;
125126
&pgupgrade;
126127
&seg;

doc/src/sgml/filelist.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml">
130130
<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml">
131131
<!ENTITY pgtestfsync SYSTEM "pgtestfsync.sgml">
132+
<!ENTITY pgtesttiming SYSTEM "pgtesttiming.sgml">
132133
<!ENTITY pgtrgm SYSTEM "pgtrgm.sgml">
133134
<!ENTITY pgupgrade SYSTEM "pgupgrade.sgml">
134135
<!ENTITY seg SYSTEM "seg.sgml">

doc/src/sgml/perform.sgml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,9 @@ ROLLBACK;
770770
network transmission costs and I/O conversion costs are not included.
771771
Second, the measurement overhead added by <command>EXPLAIN
772772
ANALYZE</command> can be significant, especially on machines with slow
773-
<function>gettimeofday()</> operating-system calls.
773+
<function>gettimeofday()</> operating-system calls. You can use the
774+
<xref linkend="pgtesttiming"> tool to measure the overhead of timing
775+
on your system.
774776
</para>
775777

776778
<para>

0 commit comments

Comments
 (0)