diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-03-14 12:02:33 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-03-15 09:27:25 +0200 |
commit | 87279b57516dfd891ef03858dac1d644df758b4c (patch) | |
tree | cd45ffc5d34e94749a77987975555996c22188c9 /src/fetchkeys.c | |
download | cache-benchmarks-87279b57516dfd891ef03858dac1d644df758b4c.tar.gz cache-benchmarks-87279b57516dfd891ef03858dac1d644df758b4c.tar.bz2 |
Initial commit
Diffstat (limited to 'src/fetchkeys.c')
-rw-r--r-- | src/fetchkeys.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/fetchkeys.c b/src/fetchkeys.c new file mode 100644 index 0000000..32f0199 --- /dev/null +++ b/src/fetchkeys.c @@ -0,0 +1,320 @@ +#include <stdio.h> +#include <stdlib.h> +#include <gdbm.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <signal.h> +#include <assert.h> +#include <sys/time.h> +#include <sys/stat.h> + +static unsigned long +get_size (char const *str) +{ + char *p; + unsigned long n, m; + + errno = 0; + n = strtoul (str, &p, 10); + if (errno) + { + perror (str); + exit (1); + } + switch (*p) + { + case 0: + m = 1; + break; + + case 'k': + case 'K': + p++; + m = 1024; + break; + + case 'm': + case 'M': + p++; + m = 1024 * 1024; + break; + } + + if (*p) + { + fprintf (stderr, "%s: bad number (near %s)\n", str, p); + exit (1); + } + + if (ULONG_MAX / m < n) + { + fprintf (stderr, "%s: number too big\n", str); + exit (1); + } + return m * n; +} + +#ifdef DUMPSTATS +static void +dump_stats (GDBM_FILE dbf, size_t n) +{ + static size_t cache_size; + static struct gdbm_cache_stat *stat; + size_t access_count, cache_count; + FILE *fp; + char fname[80]; + size_t i; + + if (cache_size == 0) + { + if (gdbm_setopt (dbf, GDBM_GETCACHESIZE, &cache_size, sizeof(cache_size))) + { + fprintf (stderr, "GDBM_GETCACHESIZE: %s\n", + gdbm_strerror (gdbm_errno)); + exit (1); + } + stat = calloc (cache_size, sizeof (stat[0])); + assert (stat != NULL); + } + + gdbm_get_cache_stats (dbf, &access_count, &cache_count, stat, cache_size); + + snprintf (fname, sizeof (fname), "%zu.stat", n); + + fp = fopen (fname, "w"); + assert (fp != NULL); + + fprintf (fp, "%zu\n", access_count); + fprintf (fp, "%zu\n", cache_count); + for (i = 0; i < cache_count; i++) + { + fprintf (fp, "%zu %zu\n", stat[i].adr, stat[i].hits); + } + fclose (fp); + + fprintf (stderr, "%80.80s\rDump file %s\n", "", fname); +} + +static volatile int statsig; + +void +sighan (int sig) +{ + statsig = 1; + signal (sig, sighan); +} +#endif + +char *dbname = "a.gdbm"; +char *kfname = "keys.txt"; +int percent; +int verbose = 0; +int time_verbose = 1; + +char *keybuf; +char *keyptr; +char *keyend; +size_t nkeys; + +char * +nextkey (void) +{ + char *ret = keyptr; + + if (keyptr >= keyend) + return NULL; + keyptr += strlen (keyptr) + 1; + return ret; +} + +void +readkeys (char const *name) +{ + FILE *fp; + size_t n; + struct stat st; + char *p; + + if (stat (name, &st)) + { + fprintf (stderr, "%s: can't stat: %s\n", name, strerror (errno)); + exit (1); + } + + fp = fopen (name, "r"); + if (!fp) + { + fprintf (stderr, "%s: can't read: %s\n", name, strerror (errno)); + exit (1); + } + + keybuf = malloc (st.st_size + 1); + assert (keybuf != NULL); + keyend = keybuf + st.st_size; + *keyend = 0; + + if (fread (keybuf, st.st_size, 1, fp) != 1) + { + fprintf (stderr, "%s: read error: %s\n", name, strerror (errno)); + exit (1); + } + fclose (fp); + keyptr = keybuf; + + nkeys = 0; + for (p = keybuf; p < keyend; p++) + if (*p == '\n') + { + *p = 0; + nkeys++; + } +} + +int +main (int argc, char **argv) +{ + GDBM_FILE dbf; + datum key; + datum data; + int status = 0; + int i; + int print = 0; + unsigned long maxsize = 0; + int flags = 0; + struct timeval t_start, t_open, t_now, td; + char *keystr; + + while ((i = getopt (argc, argv, "c:t:nTpv")) != EOF) + { + switch (i) + { + case 'n': + flags |= GDBM_NOMMAP; + break; + + case 'p': + print = 1; + break; + + case 'c': + maxsize = get_size (optarg); + break; + + case 'T': + time_verbose = 0; + break; + + case 'v': + verbose = 1; + break; + + default: + exit (1); + } + } + + argc -= optind; + argv += optind; + + switch (argc) + { + case 2: + kfname = argv[1]; + case 1: + dbname = argv[0]; + break; + case 0: + break; + default: + fprintf (stderr, "too many arguments\n"); + exit (1); + } + + if (verbose) + printf ("PID %u\n", getpid ()); + +#ifdef DUMPSTATS + signal (SIGUSR1, sighan); +#endif + + gettimeofday (&t_start, NULL); + dbf = gdbm_open (dbname, 0, GDBM_READER | flags, 00664, NULL); + assert (dbf != NULL); + gettimeofday (&t_open, NULL); + + if (maxsize) + { + int rc = gdbm_setopt (dbf, GDBM_SETCACHESIZE, &maxsize, sizeof (maxsize)); + if (rc) + { + fprintf (stderr, "GDBM_SETCACHESIZE: %s\n", gdbm_strerror (gdbm_errno)); + return 1; + } + } + + readkeys (kfname); + i = 0; + while ((keystr = nextkey ()) != NULL) + { + i++; + + if (verbose) + { + unsigned long long k = (unsigned long long) i * 100 / nkeys; + gettimeofday (&t_now, NULL); + timersub (&t_now, &t_start, &td); + printf ("%8u %6zu / %6zu % 2d%%\r", td.tv_sec, i, nkeys, k); + fflush (stdout); + } + +#ifdef DUMPSTATS + if (statsig) + { + dump_stats (dbf, i); + statsig = 0; + } +#endif + + key.dptr = keystr; + key.dsize = strlen (key.dptr); + data = gdbm_fetch (dbf, key); + if (data.dptr == NULL) + { + status = 2; + if (gdbm_errno == GDBM_ITEM_NOT_FOUND) + { + fprintf (stderr, "%s: not found\n", keystr); + } + else + { + fprintf (stderr, "%s: error: %s\n", keystr, + gdbm_strerror (gdbm_errno)); + } + continue; + } + if (print) + printf ("%s: %*.*s\n", keystr, data.dsize, data.dsize, data.dptr); + free (data.dptr); + } + gdbm_close (dbf); + if (verbose) + putchar ('\n'); + if (time_verbose) + { + gettimeofday (&t_now, NULL); + timersub (&t_now, &t_start, &td); + printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec); + timersub (&t_open, &t_start, &td); + printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec); + timersub (&t_now, &t_open, &td); + printf ("%lu.%06lu\n", td.tv_sec, td.tv_usec); + } + return status; +} + + + + + |