aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-06-14 15:41:37 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-06-14 18:13:40 +0300
commitd69a106c04a6a7abe65e9150e5bf211d35a757f0 (patch)
treeef6110350999bc33523d52c9bb424c8dc9d03510
parent72af65ca06eeec98266fce0c474d5bfbc3d91951 (diff)
downloadgdbm-d69a106c04a6a7abe65e9150e5bf211d35a757f0.tar.gz
gdbm-d69a106c04a6a7abe65e9150e5bf211d35a757f0.tar.bz2
Enable pre-reading the memory mapped regions on request.
The commit 4fb2326a4a introduced pre-reading of memory mapped regions. While speeding up searches, it has a negative impact on write operatons, since every remapping effectively re-reads the entire database. See https://github.com/Perl/perl5/issues/18884 for details. * NEWS: Document changes. * doc/gdbm.texi: Document the GDBM_PREREAD flag. * src/gdbm.h.in (GDBM_PREREAD): New flag. * src/gdbmdefs.h (gdbm_file_info): New member: mmap_preread. * src/gdbmopen.c (gdbm_fd_open): Set mmap_preread if requested. * src/gdbmsetopt.c (setopt_gdbm_getflags): Report GDBM_PREREAD flag, if dbf->mmap_preread is set. * src/mmap.c (_gdbm_internal_remap): Use pre-fault reading only if dbf->mmap_preread is set.
-rw-r--r--NEWS12
-rw-r--r--doc/gdbm.texi16
-rw-r--r--src/gdbm.h.in21
-rw-r--r--src/gdbmdefs.h1
-rw-r--r--src/gdbmopen.c1
-rw-r--r--src/gdbmsetopt.c2
-rw-r--r--src/mmap.c15
7 files changed, 52 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index f4741e0..e7c8216 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU dbm NEWS -- history of user-visible changes. 2021-03-23
+GNU dbm NEWS -- history of user-visible changes. 2021-06-14
Copyright (C) 1990-2021 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -12,6 +12,16 @@ The bucket cache support has been rewritten from scratch. The new
bucket cache code provides for significant speed up of search
operations.
+* Change mmap prereading strategy
+
+Pre-reading of the memory mapper regions, introduced in version 1.19
+can be advantageous only when doing intensive look-ups on a read-only
+database. It degrades performance otherwise, especially if doing
+multiple inserts. Therefore, this version introduces a new flag
+to gdbm_open: GDBM_PREREAD. When given, it enables pre-reading of
+memory mapped regions.
+
+See https://github.com/Perl/perl5/issues/18884 for details.
Version 1.19 - 2020-12-23
diff --git a/doc/gdbm.texi b/doc/gdbm.texi
index 5f42ced..1aec85a 100644
--- a/doc/gdbm.texi
+++ b/doc/gdbm.texi
@@ -411,6 +411,22 @@ locking separately.
@item GDBM_NOMMAP
Disable memory mapping mechanism. This degrades performance.
+@kwindex GDBM_PREREAD
+@item GDBM_PREREAD
+When mapping GDBM file to memory, read its contents immediately,
+instead of when needed (@dfn{prefault reading}). This can be
+advantageous if you open a @emph{read-only} database and are going to
+do a lot of look-ups on it. In this case entire database will be
+pre-read and look-ups will operate on an in-memory copy. In the
+contrast, @code{GDBM_PREREAD} should not be used if you open a
+database (even in read-only mode) only to do a couple of look-ups.
+Finally, never use @code{GDBM_PREREAD} when opening a database for
+updates, especially for inserts: this will degrade performance.
+
+This flag has no effect if @code{GDBM_NOMMAP} is given, or if the
+operating system does not support prefault reading. It is known
+to work on Linux and FreeBSD kernels.
+
@kwindex GDBM_BSEXACT
@item GDBM_BSEXACT
If this flag is set and the requested @var{block_size} cannot be used
diff --git a/src/gdbm.h.in b/src/gdbm.h.in
index 1cd54c4..a916457 100644
--- a/src/gdbm.h.in
+++ b/src/gdbm.h.in
@@ -44,16 +44,17 @@ extern "C" {
# define GDBM_NEWDB 3 /* A writer. Always create a new db. */
# define GDBM_OPENMASK 7 /* Mask for the above. */
-# define GDBM_FAST 0x010 /* Write fast! => No fsyncs. OBSOLETE. */
-# define GDBM_SYNC 0x020 /* Sync operations to the disk. */
-# define GDBM_NOLOCK 0x040 /* Don't do file locking operations. */
-# define GDBM_NOMMAP 0x080 /* Don't use mmap(). */
-# define GDBM_CLOEXEC 0x100 /* Close the underlying fd on exec(3) */
-# define GDBM_BSEXACT 0x200 /* Don't adjust block_size. Bail out with
+# define GDBM_FAST 0x0010 /* Write fast! => No fsyncs. OBSOLETE. */
+# define GDBM_SYNC 0x0020 /* Sync operations to the disk. */
+# define GDBM_NOLOCK 0x0040 /* Don't do file locking operations. */
+# define GDBM_NOMMAP 0x0080 /* Don't use mmap(). */
+# define GDBM_CLOEXEC 0x0100 /* Close the underlying fd on exec(3) */
+# define GDBM_BSEXACT 0x0200 /* Don't adjust block_size. Bail out with
GDBM_BLOCK_SIZE_ERROR error if unable to
set it. */
-# define GDBM_CLOERROR 0x400 /* Only for gdbm_fd_open: close fd on error. */
-# define GDBM_XVERIFY 0x800 /* Additional consistency checks. */
+# define GDBM_CLOERROR 0x0400 /* Only for gdbm_fd_open: close fd on error. */
+# define GDBM_XVERIFY 0x0800 /* Additional consistency checks. */
+# define GDBM_PREREAD 0x1000
/* Parameters to gdbm_store for simple insertion or replacement in the
case that the key is already in the database. */
@@ -62,7 +63,7 @@ extern "C" {
/* Parameters to gdbm_setopt, specifing the type of operation to perform. */
# define GDBM_SETCACHESIZE 1 /* Set the cache size. */
-# define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */
+# define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */
# define GDBM_SETSYNCMODE 3 /* Turn on or off sync operations. */
# define GDBM_SETCENTFREE 4 /* Keep all free blocks in the header. */
# define GDBM_SETCOALESCEBLKS 5 /* Attempt to coalesce free blocks. */
@@ -88,7 +89,7 @@ extern "C" {
# define GDBM_CACHE_AUTO 0
typedef @GDBM_COUNT_T@ gdbm_count_t;
-
+
/* The data and key structure. */
typedef struct
{
diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h
index e746ac3..a5daddd 100644
--- a/src/gdbmdefs.h
+++ b/src/gdbmdefs.h
@@ -272,6 +272,7 @@ struct gdbm_file_info
off_t mapped_pos; /* Current offset in the region */
off_t mapped_off; /* Position in the file where the region
begins */
+ int mmap_preread :1; /* 1 if prefault reading is requested */
};
#define GDBM_DIR_COUNT(db) ((db)->header->dir_size / sizeof (off_t))
diff --git a/src/gdbmopen.c b/src/gdbmopen.c
index 39ec928..8092432 100644
--- a/src/gdbmopen.c
+++ b/src/gdbmopen.c
@@ -556,6 +556,7 @@ gdbm_fd_open (int fd, const char *file_name, int block_size,
#if HAVE_MMAP
if (!(flags & GDBM_NOMMAP))
{
+ dbf->mmap_preread = (flags & GDBM_PREREAD) != 0;
if (_gdbm_mapped_init (dbf) == 0)
dbf->memory_mapping = TRUE;
else
diff --git a/src/gdbmsetopt.c b/src/gdbmsetopt.c
index c6f2052..a49ea40 100644
--- a/src/gdbmsetopt.c
+++ b/src/gdbmsetopt.c
@@ -260,6 +260,8 @@ setopt_gdbm_getflags (GDBM_FILE dbf, void *optval, int optlen)
flags |= GDBM_NOLOCK;
if (!dbf->memory_mapping)
flags |= GDBM_NOMMAP;
+ else if (dbf->mmap_preread)
+ flags |= GDBM_PREREAD;
*(int*) optval = flags;
}
return 0;
diff --git a/src/mmap.c b/src/mmap.c
index 8d5e6c6..778cf46 100644
--- a/src/mmap.c
+++ b/src/mmap.c
@@ -33,11 +33,11 @@
# endif
# if defined(MAP_POPULATE)
-# define GDBM_MMAP_FLAGS MAP_POPULATE
+# define GDBM_MMAP_PREREAD MAP_POPULATE
# elif defined(MAP_PREFAULT_READ)
-# define GDBM_MMAP_FLAGS MAP_PREFAULT_READ
+# define GDBM_MMAP_PREREAD MAP_PREFAULT_READ
# else
-# define GDBM_MMAP_FLAGS 0
+# define GDBM_MMAP_PREREAD 0
# endif
/* Translate current offset in the mapped region into the absolute position */
@@ -82,6 +82,7 @@ int
_gdbm_internal_remap (GDBM_FILE dbf, size_t size)
{
void *p;
+ int flags = MAP_SHARED;
int prot = PROT_READ;
size_t page_size = sysconf (_SC_PAGESIZE);
@@ -100,9 +101,13 @@ _gdbm_internal_remap (GDBM_FILE dbf, size_t size)
if (dbf->read_write)
prot |= PROT_WRITE;
+
+ if (dbf->mmap_preread)
+ {
+ flags |= GDBM_MMAP_PREREAD;
+ }
- p = mmap (NULL, dbf->mapped_size, prot, MAP_SHARED | GDBM_MMAP_FLAGS,
- dbf->desc, dbf->mapped_off);
+ p = mmap (NULL, dbf->mapped_size, prot, flags, dbf->desc, dbf->mapped_off);
if (p == MAP_FAILED)
{
dbf->mapped_region = NULL;

Return to:

Send suggestions and report system problems to the System administrator.