diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2015-03-10 22:33:24 -0400 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2015-04-20 21:30:12 -0400 |
commit | 528c2e44ab0a5ba49a5a04689dae3f674b71c15e (patch) | |
tree | 89ffd862071c596ee5ab36710f6982ff013084e9 /src/bin/pg_test_timing | |
parent | d992f8a8961c09ec219373ffe2b5e6473febd065 (diff) | |
download | postgresql-528c2e44ab0a5ba49a5a04689dae3f674b71c15e.tar.gz postgresql-528c2e44ab0a5ba49a5a04689dae3f674b71c15e.zip |
Move pg_test_timing from contrib/ to src/bin/
Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
Diffstat (limited to 'src/bin/pg_test_timing')
-rw-r--r-- | src/bin/pg_test_timing/.gitignore | 1 | ||||
-rw-r--r-- | src/bin/pg_test_timing/Makefile | 27 | ||||
-rw-r--r-- | src/bin/pg_test_timing/pg_test_timing.c | 188 |
3 files changed, 216 insertions, 0 deletions
diff --git a/src/bin/pg_test_timing/.gitignore b/src/bin/pg_test_timing/.gitignore new file mode 100644 index 00000000000..f6c664c7657 --- /dev/null +++ b/src/bin/pg_test_timing/.gitignore @@ -0,0 +1 @@ +/pg_test_timing diff --git a/src/bin/pg_test_timing/Makefile b/src/bin/pg_test_timing/Makefile new file mode 100644 index 00000000000..d1f35954f0f --- /dev/null +++ b/src/bin/pg_test_timing/Makefile @@ -0,0 +1,27 @@ +# src/bin/pg_test_timing/Makefile + +PGFILEDESC = "pg_test_timing - test timing overhead" +PGAPPICON = win32 + +subdir = src/bin/pg_test_timing +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +OBJS = pg_test_timing.o $(WIN32RES) + +all: pg_test_timing + +pg_test_timing: $(OBJS) | submake-libpgport + $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_test_timing$(X) '$(DESTDIR)$(bindir)/pg_test_timing$(X)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f '$(DESTDIR)$(bindir)/pg_test_timing$(X)' + +clean distclean maintainer-clean: + rm -f pg_test_timing$(X) $(OBJS) diff --git a/src/bin/pg_test_timing/pg_test_timing.c b/src/bin/pg_test_timing/pg_test_timing.c new file mode 100644 index 00000000000..e5c11de6bb4 --- /dev/null +++ b/src/bin/pg_test_timing/pg_test_timing.c @@ -0,0 +1,188 @@ +/* + * pg_test_timing.c + * tests overhead of timing calls and their monotonicity: that + * they always move forward + */ + +#include "postgres_fe.h" + +#include "getopt_long.h" +#include "portability/instr_time.h" + +static const char *progname; + +static int32 test_duration = 3; + +static void handle_args(int argc, char *argv[]); +static uint64 test_timing(int32); +static void output(uint64 loop_count); + +/* record duration in powers of 2 microseconds */ +int64 histogram[32]; + +int +main(int argc, char *argv[]) +{ + uint64 loop_count; + + progname = get_progname(argv[0]); + + handle_args(argc, argv); + + loop_count = test_timing(test_duration); + + output(loop_count); + + return 0; +} + +static void +handle_args(int argc, char *argv[]) +{ + static struct option long_options[] = { + {"duration", required_argument, NULL, 'd'}, + {NULL, 0, NULL, 0} + }; + + int option; /* Command line option */ + int optindex = 0; /* used by getopt_long */ + + if (argc > 1) + { + if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) + { + printf("Usage: %s [-d DURATION]\n", progname); + exit(0); + } + if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) + { + puts("pg_test_timing (PostgreSQL) " PG_VERSION); + exit(0); + } + } + + while ((option = getopt_long(argc, argv, "d:", + long_options, &optindex)) != -1) + { + switch (option) + { + case 'd': + test_duration = atoi(optarg); + break; + + default: + fprintf(stderr, "Try \"%s --help\" for more information.\n", + progname); + exit(1); + break; + } + } + + if (argc > optind) + { + fprintf(stderr, + "%s: too many command-line arguments (first is \"%s\")\n", + progname, argv[optind]); + fprintf(stderr, "Try \"%s --help\" for more information.\n", + progname); + exit(1); + } + + if (test_duration > 0) + { + printf("Testing timing overhead for %d seconds.\n", test_duration); + } + else + { + fprintf(stderr, + "%s: duration must be a positive integer (duration is \"%d\")\n", + progname, test_duration); + fprintf(stderr, "Try \"%s --help\" for more information.\n", + progname); + exit(1); + } +} + +static uint64 +test_timing(int32 duration) +{ + uint64 total_time; + int64 time_elapsed = 0; + uint64 loop_count = 0; + uint64 prev, + cur; + instr_time start_time, + end_time, + temp; + + total_time = duration > 0 ? duration * INT64CONST(1000000) : 0; + + INSTR_TIME_SET_CURRENT(start_time); + cur = INSTR_TIME_GET_MICROSEC(start_time); + + while (time_elapsed < total_time) + { + int32 diff, + bits = 0; + + prev = cur; + INSTR_TIME_SET_CURRENT(temp); + cur = INSTR_TIME_GET_MICROSEC(temp); + diff = cur - prev; + + /* Did time go backwards? */ + if (diff < 0) + { + printf("Detected clock going backwards in time.\n"); + printf("Time warp: %d microseconds\n", diff); + exit(1); + } + + /* What is the highest bit in the time diff? */ + while (diff) + { + diff >>= 1; + bits++; + } + + /* Update appropriate duration bucket */ + histogram[bits]++; + + loop_count++; + INSTR_TIME_SUBTRACT(temp, start_time); + time_elapsed = INSTR_TIME_GET_MICROSEC(temp); + } + + INSTR_TIME_SET_CURRENT(end_time); + + INSTR_TIME_SUBTRACT(end_time, start_time); + + printf("Per loop time including overhead: %0.2f nsec\n", + INSTR_TIME_GET_DOUBLE(end_time) * 1e9 / loop_count); + + return loop_count; +} + +static void +output(uint64 loop_count) +{ + int64 max_bit = 31, + i; + + /* find highest bit value */ + while (max_bit > 0 && histogram[max_bit] == 0) + max_bit--; + + printf("Histogram of timing durations:\n"); + printf("%6s %10s %10s\n", "< usec", "% of total", "count"); + + for (i = 0; i <= max_bit; i++) + { + char buf[100]; + + /* lame hack to work around INT64_FORMAT deficiencies */ + snprintf(buf, sizeof(buf), INT64_FORMAT, histogram[i]); + printf("%6ld %9.5f %10s\n", 1l << i, + (double) histogram[i] * 100 / loop_count, buf); + } +} |