summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2020-03-14 10:02:33 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2020-03-15 07:27:25 (GMT)
commit87279b57516dfd891ef03858dac1d644df758b4c (patch) (unidiff)
treecd45ffc5d34e94749a77987975555996c22188c9
downloadcache-benchmarks-87279b57516dfd891ef03858dac1d644df758b4c.tar.gz
cache-benchmarks-87279b57516dfd891ef03858dac1d644df758b4c.tar.bz2
Initial commit
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore39
-rw-r--r--.gitmodules7
-rw-r--r--Makefile.am22
-rw-r--r--bootstrap8
-rw-r--r--configure.ac18
m---------gdbm/master0
m---------gdbm/newcache0
-rw-r--r--src/.gitignore3
-rw-r--r--src/Makefile.am2
-rw-r--r--src/benchmark.mk.in50
-rw-r--r--src/dropcache.c24
-rw-r--r--src/fetchkeys.c320
-rw-r--r--src/gnuplot.m413
-rw-r--r--src/master/Makefile.am5
-rw-r--r--src/newcache/Makefile.am5
-rwxr-xr-xsrc/runtest97
16 files changed, 613 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b2a687e
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
1*.a
2*.la
3*.lo
4*.o
5*.orig
6*.pyc
7*.rej
8*.tar.bz2
9*.tar.gz
10*.tar.xz
11*~
12*.gdbm
13*.cflow
14.deps
15.emacs*
16.libs
17ABOUT-NLS
18ChangeLog
19INSTALL
20Makefile
21Makefile.in
22TAGS
23aclocal.m4
24autoconf.h
25autoconf.h.in
26autom4te.cache
27build-aux
28config.log
29config.status
30configure
31configure.ac
32core
33gmon.out
34libltdl
35libtool
36m4
37stamp-h1
38tmp/
39benchmarks
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..a4fd957
--- a/dev/null
+++ b/.gitmodules
@@ -0,0 +1,7 @@
1[submodule "gdbm/newcache"]
2 path = gdbm/newcache
3 url = git://git.gnu.org.ua/gdbm.git
4 branch = newcache
5[submodule "gdbm/master"]
6 path = gdbm/master
7 url = git://git.gnu.org.ua/gdbm.git
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a7c97e1
--- a/dev/null
+++ b/Makefile.am
@@ -0,0 +1,22 @@
1ACLOCAL_AMFLAGS = -I m4
2SUBDIRS = gdbm/master gdbm/newcache src
3BENCHMARKDIR=benchmarks
4benchmark:
5 @if test -z "$(NRECS)"; then \
6 echo "Please set NRECS"; \
7 exit 1; \
8 fi; \
9 if test -z "$(NKEYS)"; then \
10 echo "Please set NKEYS"; \
11 exit 1; \
12 fi; \
13 DIRNAME="$(BENCHMARKDIR)/$(NRECS)-$(NKEYS)"; \
14 if ! test -d "$$DIRNAME"; then \
15 mkdir -p $$DIRNAME; \
16 (echo "NRECS=$(NRECS)"; \
17 echo "NKEYS=$(NKEYS)"; \
18 echo "MAXCACHE=$(MAXCACHE)"; \
19 echo "include @abs_top_builddir@/src/benchmark.mk") > $$DIRNAME/Makefile; \
20 fi; \
21 $(MAKE) -C $$DIRNAME
22
diff --git a/bootstrap b/bootstrap
new file mode 100644
index 0000000..1726aea
--- a/dev/null
+++ b/bootstrap
@@ -0,0 +1,8 @@
1#!/bin/sh
2set e
3test -d m4 || mkdir m4
4test -d gdbm || mkdir gdbm
5git submodule init
6git submodule update
7git submodule foreach ./bootstrap
8autoreconf -f -i -s
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..5abd4ff
--- a/dev/null
+++ b/configure.ac
@@ -0,0 +1,18 @@
1AC_PREREQ([2.69])
2AC_INIT([gdbm-benchmarks],[0.1],[gray@gnu.org],
3 [gdbm-benchmarks],
4 [https://puszcza.gnu.org.ua/projects/gdbm])
5AC_CONFIG_SRCDIR([src/fetchkeys.c])
6AC_CONFIG_AUX_DIR([build-aux])
7AM_INIT_AUTOMAKE([-Wall -Werror 1.11.5 foreign tar-ustar silent-rules])
8
9# Checks for programs.
10AC_PROG_CC
11
12AC_CONFIG_SUBDIRS(gdbm/master gdbm/newcache)
13AC_CONFIG_FILES([Makefile
14 src/Makefile
15 src/master/Makefile
16 src/newcache/Makefile
17 src/benchmark.mk])
18AC_OUTPUT
diff --git a/gdbm/master b/gdbm/master
new file mode 160000
Subproject 4fb2326a4ac0e6f45c21f7651b1c87317567fd8
diff --git a/gdbm/newcache b/gdbm/newcache
new file mode 160000
Subproject 1f94a81a9f3a9955ca74dff07b7909595a85048
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..ef23521
--- a/dev/null
+++ b/src/.gitignore
@@ -0,0 +1,3 @@
1dropcache
2fetchkeys
3benchmark.mk
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..c019df3
--- a/dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,2 @@
1SUBDIRS=newcache master
2EXTRA_DIST=fechkeys.c runtest gnuplot.m4 benchmark.mk.in
diff --git a/src/benchmark.mk.in b/src/benchmark.mk.in
new file mode 100644
index 0000000..c576cd6
--- a/dev/null
+++ b/src/benchmark.mk.in
@@ -0,0 +1,50 @@
1AM_DEFAULT_VERBOSITY=0
2AM_V_P = $(am__v_P_@AM_V@)
3am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
4am__v_P_0 = false
5am__v_P_1 = :
6AM_V_GEN = $(am__v_GEN_@AM_V@)
7am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
8am__v_GEN_0 = @echo " GEN " $@;
9am__v_GEN_1 =
10AM_V_at = $(am__v_at_@AM_V@)
11am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
12am__v_at_0 = @
13am__v_at_1 =
14
15abs_top_srcdir = @abs_top_srcdir@
16abs_top_builddir = @abs_top_builddir@
17
18MASTERDIR=$(abs_top_builddir)/gdbm/master
19GDBMTOOL=$(MASTERDIR)/src/gdbmtool
20TESTDIR=$(MASTERDIR)/tests
21
22all: test
23test: master.log newcache.log
24%.log: keys.txt a.gdbm
25 $(AM_V_GEN)MAXCACHE=$(MAXCACHE); \
26 $(abs_top_srcdir)/src/runtest -d \
27 --final $${MAXCACHE:-$$(($$($(GDBMTOOL) a.gdbm dir |\
28 sed -n -e '2{' \
29 -e 's/.*Buckets = //' \
30 -e 's/\.$$//' \
31 -e 'p}') * 2))} \
32 --log-file=$*.log \
33 $(abs_top_builddir)/src/$*/fetchkeys
34clean:
35 rm -f master.log newcache.log
36allclean: clean
37 rm -f keys.txt a.gdbm
38keys.txt:
39 @$(MAKE) -C $(TESTDIR) num2word
40 $(AM_V_GEN)$(TESTDIR)/num2word 1:$(NRECS) | \
41 cut -f1 | shuf | head -n $(NKEYS) > keys.txt
42a.gdbm:
43 @$(MAKE) -C $(TESTDIR) num2word gtload
44 $(AM_V_GEN)$(TESTDIR)/num2word 1:$(NRECS) | $(TESTDIR)/gtload -clear a.gdbm
45benchmark.gnuplot: $(abs_top_srcdir)/src/gnuplot.m4
46 m4 -DNRECS=$(NRECS) -DNKEYS=$(NKEYS) \
47 $(abs_top_srcdir)/src/gnuplot.m4 > benchmark.gnuplot
48plot: test benchmark.gnuplot
49 gnuplot -p benchmark.gnuplot
50
diff --git a/src/dropcache.c b/src/dropcache.c
new file mode 100644
index 0000000..659f00a
--- a/dev/null
+++ b/src/dropcache.c
@@ -0,0 +1,24 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <fcntl.h>
4
5char const drop_caches[] = "/proc/sys/vm/drop_caches";
6
7int
8main(int argc, char **argv)
9{
10 int fd;
11 fd = open(drop_caches, O_WRONLY);
12 if (fd == -1)
13 {
14 perror(drop_caches);
15 return 1;
16 }
17 if (write(fd, "3\n", 2) != 2)
18 {
19 perror(drop_caches);
20 return 1;
21 }
22 close(fd);
23 return 0;
24}
diff --git a/src/fetchkeys.c b/src/fetchkeys.c
new file mode 100644
index 0000000..32f0199
--- a/dev/null
+++ b/src/fetchkeys.c
@@ -0,0 +1,320 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <gdbm.h>
4#include <string.h>
5#include <unistd.h>
6#include <limits.h>
7#include <errno.h>
8#include <signal.h>
9#include <assert.h>
10#include <sys/time.h>
11#include <sys/stat.h>
12
13static unsigned long
14get_size (char const *str)
15{
16 char *p;
17 unsigned long n, m;
18
19 errno = 0;
20 n = strtoul (str, &p, 10);
21 if (errno)
22 {
23 perror (str);
24 exit (1);
25 }
26 switch (*p)
27 {
28 case 0:
29 m = 1;
30 break;
31
32 case 'k':
33 case 'K':
34 p++;
35 m = 1024;
36 break;
37
38 case 'm':
39 case 'M':
40 p++;
41 m = 1024 * 1024;
42 break;
43 }
44
45 if (*p)
46 {
47 fprintf (stderr, "%s: bad number (near %s)\n", str, p);
48 exit (1);
49 }
50
51 if (ULONG_MAX / m < n)
52 {
53 fprintf (stderr, "%s: number too big\n", str);
54 exit (1);
55 }
56 return m * n;
57}
58
59#ifdef DUMPSTATS
60static void
61dump_stats (GDBM_FILE dbf, size_t n)
62{
63 static size_t cache_size;
64 static struct gdbm_cache_stat *stat;
65 size_t access_count, cache_count;
66 FILE *fp;
67 char fname[80];
68 size_t i;
69
70 if (cache_size == 0)
71 {
72 if (gdbm_setopt (dbf, GDBM_GETCACHESIZE, &cache_size, sizeof(cache_size)))
73 {
74 fprintf (stderr, "GDBM_GETCACHESIZE: %s\n",
75 gdbm_strerror (gdbm_errno));
76 exit (1);
77 }
78 stat = calloc (cache_size, sizeof (stat[0]));
79 assert (stat != NULL);
80 }
81
82 gdbm_get_cache_stats (dbf, &access_count, &cache_count, stat, cache_size);
83
84 snprintf (fname, sizeof (fname), "%zu.stat", n);
85
86 fp = fopen (fname, "w");
87 assert (fp != NULL);
88
89 fprintf (fp, "%zu\n", access_count);
90 fprintf (fp, "%zu\n", cache_count);
91 for (i = 0; i < cache_count; i++)
92 {
93 fprintf (fp, "%zu %zu\n", stat[i].adr, stat[i].hits);
94 }
95 fclose (fp);
96
97 fprintf (stderr, "%80.80s\rDump file %s\n", "", fname);
98}
99
100static volatile int statsig;
101
102void
103sighan (int sig)
104{
105 statsig = 1;
106 signal (sig, sighan);
107}
108#endif
109
110char *dbname = "a.gdbm";
111char *kfname = "keys.txt";
112int percent;
113int verbose = 0;
114int time_verbose = 1;
115
116char *keybuf;
117char *keyptr;
118char *keyend;
119size_t nkeys;
120
121char *
122nextkey (void)
123{
124 char *ret = keyptr;
125
126 if (keyptr >= keyend)
127 return NULL;
128 keyptr += strlen (keyptr) + 1;
129 return ret;
130}
131
132void
133readkeys (char const *name)
134{
135 FILE *fp;
136 size_t n;
137 struct stat st;
138 char *p;
139
140 if (stat (name, &st))
141 {
142 fprintf (stderr, "%s: can't stat: %s\n", name, strerror (errno));
143 exit (1);
144 }
145
146 fp = fopen (name, "r");
147 if (!fp)
148 {
149 fprintf (stderr, "%s: can't read: %s\n", name, strerror (errno));
150 exit (1);
151 }
152
153 keybuf = malloc (st.st_size + 1);
154 assert (keybuf != NULL);
155 keyend = keybuf + st.st_size;
156 *keyend = 0;
157
158 if (fread (keybuf, st.st_size, 1, fp) != 1)
159 {
160 fprintf (stderr, "%s: read error: %s\n", name, strerror (errno));
161 exit (1);
162 }
163 fclose (fp);
164 keyptr = keybuf;
165
166 nkeys = 0;
167 for (p = keybuf; p < keyend; p++)
168 if (*p == '\n')
169 {
170 *p = 0;
171 nkeys++;
172 }
173}
174
175int
176main (int argc, char **argv)
177{
178 GDBM_FILE dbf;
179 datum key;
180 datum data;
181 int status = 0;
182 int i;
183 int print = 0;
184 unsigned long maxsize = 0;
185 int flags = 0;
186 struct timeval t_start, t_open, t_now, td;
187 char *keystr;
188
189 while ((i = getopt (argc, argv, "c:t:nTpv")) != EOF)
190 {
191 switch (i)
192 {
193 case 'n':
194 flags |= GDBM_NOMMAP;
195 break;
196
197 case 'p':
198 print = 1;
199 break;
200
201 case 'c':
202 maxsize = get_size (optarg);
203 break;
204
205 case 'T':
206 time_verbose = 0;
207 break;
208
209 case 'v':
210 verbose = 1;
211 break;
212
213 default:
214 exit (1);
215 }
216 }
217
218 argc -= optind;
219 argv += optind;
220
221 switch (argc)
222 {
223 case 2:
224 kfname = argv[1];
225 case 1:
226 dbname = argv[0];
227 break;
228 case 0:
229 break;
230 default:
231 fprintf (stderr, "too many arguments\n");
232 exit (1);
233 }
234
235 if (verbose)
236 printf ("PID %u\n", getpid ());
237
238#ifdef DUMPSTATS
239 signal (SIGUSR1, sighan);
240#endif
241
242 gettimeofday (&t_start, NULL);
243 dbf = gdbm_open (dbname, 0, GDBM_READER | flags, 00664, NULL);
244 assert (dbf != NULL);
245 gettimeofday (&t_open, NULL);
246
247 if (maxsize)
248 {
249 int rc = gdbm_setopt (dbf, GDBM_SETCACHESIZE, &maxsize, sizeof (maxsize));
250 if (rc)
251 {
252 fprintf (stderr, "GDBM_SETCACHESIZE: %s\n", gdbm_strerror (gdbm_errno));
253 return 1;
254 }
255 }
256
257 readkeys (kfname);
258 i = 0;
259 while ((keystr = nextkey ()) != NULL)
260 {
261 i++;
262
263 if (verbose)
264 {
265 unsigned long long k = (unsigned long long) i * 100 / nkeys;
266 gettimeofday (&t_now, NULL);
267 timersub (&t_now, &t_start, &td);
268 printf ("%8u %6zu / %6zu % 2d%%\r", td.tv_sec, i, nkeys, k);
269 fflush (stdout);
270 }
271
272#ifdef DUMPSTATS
273 if (statsig)
274 {
275 dump_stats (dbf, i);
276 statsig = 0;
277 }
278#endif
279
280 key.dptr = keystr;
281 key.dsize = strlen (key.dptr);
282 data = gdbm_fetch (dbf, key);
283 if (data.dptr == NULL)
284 {
285 status = 2;
286 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
287 {
288 fprintf (stderr, "%s: not found\n", keystr);
289 }
290 else
291 {
292 fprintf (stderr, "%s: error: %s\n", keystr,
293 gdbm_strerror (gdbm_errno));
294 }
295 continue;
296 }
297 if (print)
298 printf ("%s: %*.*s\n", keystr, data.dsize, data.dsize, data.dptr);
299 free (data.dptr);
300 }
301 gdbm_close (dbf);
302 if (verbose)
303 putchar ('\n');
304 if (time_verbose)
305 {
306 gettimeofday (&t_now, NULL);
307 timersub (&t_now, &t_start, &td);
308 printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
309 timersub (&t_open, &t_start, &td);
310 printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
311 timersub (&t_now, &t_open, &td);
312 printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec);
313 }
314 return status;
315}
316
317
318
319
320
diff --git a/src/gnuplot.m4 b/src/gnuplot.m4
new file mode 100644
index 0000000..7ea1a79
--- a/dev/null
+++ b/src/gnuplot.m4
@@ -0,0 +1,13 @@
1divert(-1)
2changequote([.])
3divert(0)dnl
4set title 'Execution time as function of cache size. Database size NRECS entries. Key set size NKEYS'
5show title
6set xlabel 'Cache entries'
7set ylabel 'Runtime (seconds)'
8plot 'master.log' \
9 using 1:4 smooth bezier \
10 title 'GDBM 1.18.1', \
11 'newcache.log' \
12 using 1:4 smooth bezier \
13 title 'GDBM newcache'
diff --git a/src/master/Makefile.am b/src/master/Makefile.am
new file mode 100644
index 0000000..c3adae5
--- a/dev/null
+++ b/src/master/Makefile.am
@@ -0,0 +1,5 @@
1noinst_PROGRAMS=fetchkeys
2fetchkeys_SOURCES=fetchkeys.c
3VPATH=$(top_srcdir)/src
4LDADD=../../gdbm/master/src/.libs/libgdbm.a
5AM_CPPFLAGS=-I$(top_srcdir)/gdbm/master/src/
diff --git a/src/newcache/Makefile.am b/src/newcache/Makefile.am
new file mode 100644
index 0000000..a916d36
--- a/dev/null
+++ b/src/newcache/Makefile.am
@@ -0,0 +1,5 @@
1noinst_PROGRAMS=fetchkeys
2fetchkeys_SOURCES=fetchkeys.c
3VPATH=$(top_srcdir)/src
4LDADD=../../gdbm/newcache/src/.libs/libgdbm.a
5AM_CPPFLAGS=-I$(top_srcdir)/gdbm/newcache/src/
diff --git a/src/runtest b/src/runtest
new file mode 100755
index 0000000..33322b1
--- a/dev/null
+++ b/src/runtest
@@ -0,0 +1,97 @@
1#!/bin/sh
2#! -*-perl-*-
3eval 'exec perl -x -S $0 ${1+"$@"}'
4 if 0;
5
6use strict;
7use warnings;
8use Getopt::Long qw(:config gnu_getopt no_ignore_case require_order);
9use File::Basename;
10use File::Spec;
11
12my $nsamples = 1; # Number of times to run each test.
13my $c_init = 100; # Initial cache capacity.
14my $c_step = 100; # Cache capacity increment.
15my $c_final = 100; # Final cache capacity.
16my $drop_caches; # Drop system disk caches before each run.
17my $log_file; # Name of the log file.
18
19sub runtest {
20 my ($t_total, $t_open, $t_loop) = (0,0,0);
21
22 my $n;
23 for ($n = 0; $n < $nsamples; $n++) {
24 if ($drop_caches) {
25 system($drop_caches);
26 }
27 open(PH, '-|', @_)
28 or die "can't run ".join(' ', @_).": $!\n";
29 my @inbuf;
30 while (<PH>) {
31 if (chomp) {
32 if (@inbuf == 3) {
33 print shift(@inbuf),"\n";
34 }
35 push @inbuf, $_;
36 } else {
37 print "$_";
38 }
39 }
40 close PH;
41
42 if (@inbuf == 3) {
43 $t_total += $inbuf[0];
44 $t_open += $inbuf[1];
45 $t_loop += $inbuf[2];
46 } else {
47 while (my $s = shift(@inbuf)) {
48 print "$s\n";
49 }
50 die "no timing info\n";
51 }
52 }
53 return ($t_total/$nsamples, $t_open/$nsamples, $t_loop/$nsamples)
54}
55
56GetOptions(
57 'n=n' => \$nsamples,
58 'init|i=n' => \$c_init,
59 'step|s=n' => \$c_step,
60 'final|end|e=n' => \$c_final,
61 'drop-caches|d' => sub {
62 $drop_caches = File::Spec->catfile(dirname($0), 'dropcache');
63 unless (-x $drop_caches) {
64 print STDERR <<EOT;
65$0: the option --drop-caches (-d) requires that the program $drop_caches
66be built, be owned by root, and have the setuid bit set (or the tests be
67run as root). Please, make sure that this is the case and rerun the runtest
68utility.
69EOT
70;
71 exit(1);
72 }
73 },
74 'log-file|l=s' => \$log_file
75) or exit(1);
76
77die "command line missing\n" unless @ARGV;
78
79if ($c_init > $c_final) {
80 $c_init = 10;
81}
82if ($c_step > $c_final - $c_init) {
83 $c_step = 1;
84}
85
86if ($log_file) {
87 open(LOG, '>', $log_file) or die "can't open log file $log_file: $!";
88} else {
89 open(LOG, '>&', 'STDOUT') or die "can't dup STDOUT: $!";
90}
91
92for (my $c = $c_init; $c <= $c_final; $c += $c_step) {
93 my ($t_total, $t_open, $t_loop) = runtest(@ARGV, '-c', $c);
94 printf LOG "%d %.6f %.6f %.6f\n", $c, $t_total, $t_open, $t_loop;
95}
96
97

Return to:

Send suggestions and report system problems to the System administrator.