You know that you need to use the /var/lib/ldap/DB_CONFIG file to configure the database backend to your LDAP directory (Berkeley DB) so that it will perform peppily and not get all bogged down. How do you know what options and values to use?
We'll start off with some reasonable values for starters, and then learn how to make some calculations to fine-tune them.
Be sure to check your slapd.conf for duplicate BDB entries and get rid of them. They can go in either file, but it's best to keep them all in DB_CONFIG. You don't want duplicates or conflicting entries.
First, make sure there is a cachesize
entry in
slapd.conf:
cachesize 5000
Then, enter these options and values into /var/lib/ldap/DB_CONFIG:
##/var/lib/ldap/DB_CONFIG set_cachesize 0 1048576 0 set_lk_max_objects 1500 set_lk_max_locks 1500 set_lk_max_lockers 1500 # #logging settings set_lg_regionmax 1048576 set_lg_bsize 32768 set_lg_max 131072 set_lg_dir /var/log/openldap
The set_cachesize
value is in
bytes, and must be a power of 2, so the example is one megabyte. How
do you know how much to use? Use the db4.2_stat
command on Debian, and the db_stat command on
Fedora to generate statistics from id2entry.bdb
and dn2id.bdb, which are the two main database
files:
# db4.2_stat -d /var/lib/ldap/id2entry.bdb
53162 Btree magic number. 9 Btree version number. Flags: little-endian 2 Minimum keys per-page. 16384 Underlying database page size. 1 Number of levels in the tree. 6 Number of unique keys in the tree. 6 Number of data items in the tree. 0 Number of tree internal pages. 0 Number of bytes free in tree internal pages (0% ff). 1 Number of tree leaf pages. 12374 Number of bytes free in tree leaf pages (24% ff). 0 Number of tree duplicate pages. 0 Number of bytes free in tree duplicate pages (0% ff). 0 Number of tree overflow pages. 0 Number of bytes free in tree overflow pages (0% ff). 0 Number of pages on the free list.# db4.2_stat -d /var/lib/ldap/dn2id.bdb
53162 Btree magic number. 9 Btree version number. Flags: duplicates, little-endian 2 Minimum keys per-page. 4096 Underlying database page size. 1 Number of levels in the tree. 13 Number of unique keys in the tree. 19 Number of data items in the tree. 0 Number of tree internal pages. 0 Number of bytes free in tree internal pages (0% ff). 1 Number of tree leaf pages. 3378 Number of bytes free in tree leaf pages (18% ff). 0 Number of tree duplicate pages. 0 Number of bytes free in tree duplicate pages (0% ff). 0 Number of tree overflow pages. 0 Number of bytes free in tree overflow pages (0% ff). 0 Number of pages on the free list.
You can see that each id2entry.bdb page requires 16 KB, and dn2id.bdb needs 4 KB per page, and the number of internal pages each one is using. So, you can use this formula to calculate a bare minimum memory requirement:
((50+1) * 4096) + ((12+1) * 16384)) = 421,888 bytes
This does not take into account other library overhead or indexing. As a shortcut, double this figure for decent performance. So, for this example, we could round it up to a whopping 1 MB of RAM.
How do you know what values to assign to set_lk_max_objects 1500, set_lk_max_locks
1500
, and set_lk_max_lockers
1500?
Use the db4.2_stat -c
(db_stat
on Fedora) command:
# cd /var/lib/ldap
# db4.2_stat -c
100 Last allocated locker ID.
2147M Current maximum unused locker ID.
9 Number of lock modes.
1500 Maximum number of locks possible.
1500 Maximum number of lockers possible.
1500 Maximum number of lock objects possible.
3 Number of current locks.
11 Maximum number of locks at any one time.
12 Number of current lockers.
19 Maximum number of lockers at any one time.
3 Number of current lock objects.
8 Maximum number of lock objects at any one time.
1170 Total number of locks requested.
1167 Total number of locks released.
0 Total number of lock requests failing because DB_LOCK_NOWAIT was set.
0 Total number of locks not immediately available due to conflicts.
0 Number of deadlocks.
0 Lock timeout value.
0 Number of locks that have timed out.
0 Transaction timeout value.
0 Number of transactions that have timed out.
552KB The size of the lock region..
0 The number of region locks granted after waiting.
2579 The number of region locks granted without waiting.
1500 is a reasonable starting point for a smaller directory; use
your db4.2_stat -c
output to decide
if you need to increase it. When usage hits 85 percent of your
allocated values, increase them. Look at your Number of
current values outputs, timeouts, and failures.
For OpenLDAP versions 2.3 and above, all you need to do after changing DB_CONFIG is restart slapd:
# /etc/init.d/slapd restart (Debian)
# /etc/init.d/ldap restart (Fedora)
However, this doesn't always work, so if slaptest returns errors, and is on 2.2 and older, Debian users need to use the database recovery command:
# /etc/init.d/slapd stop
# db4.2_recover -h /var/lib/ldap
# /etc/init.d/slapd start
Fedora users have slightly different commands:
# /etc/init.d/ldap stop
# db_recover -h /var/lib/ldap
# /etc/init.d/ldap start
Then, run this command to verify your new cache size. These examples are based on a value of 16777216 in DB_CONFIG. As usual, the Debian command is first, Fedora second:
# db4.2_stat -h /var/lib/ldap -m | head -n 2
20MB 1KB 604B Total cache size. 1 Number of caches.# db_stat -h /var/lib/ldap -m | head -n 2
Now, keep an eye on the performance while slapd is running. Change to the directory your database is stored in:
# cd /var/lib/ldap
# db4.2_stat -m (Debian)
# db_stat -m (Fedora)
This displays complete cache statistics.
cachesize
defines the number
of entries that the LDAP backend will keep in memory. For best
performance, this number is equal to the number of entries in your
directory, but it can be smaller. This is not the BDB cache, but
OpenLDAP's own internal cache. The default is 1000.
Watch your disk I/O—iostat
is
a good tool for this—and keep an eye on the Requested pages
found in the cache value, which you get from running
db_stat-m
in your database
directory. You want this to be as close to 100 percent as possible,
and the pages forced from the cache should be 0. If it falls under 95
percent, increase your set_cachesize
value. You want requests to be
answered from the memory cache as much as possible; you don't want a
lot of disk thrashing.
set_cachesize
has three
fields: <gbytes>,
<bytes>
, and <ncache>
. If you want to create a 2 GB
cache, it looks like set_cachesize200
. You may combine both
gigabytes and bytes. The maximum is 4 GB. Don't make your cache larger
than your total system memory. Any cache size less than 500 MB is
automatically increased by 25 percent to account for buffer pool
overhead.
ncache
tells BDB if it should
use one contiguous section of memory, or more than one. 0 or 1 means
one segment; a larger number means create that number of segments.
Modern Linux kernels support 1–3 GB per user process on 32-bit x86
systems, and don't forget that the kernel needs a good-sized chunk as
well. This example splits a 2 GB cache across two segments:
set_cachesize 2 0 2
On 64-bit systems, theoretically your whole memory space, except the bit reserved for the kernel, can be used by a single process.
Creating a too-big set_cachesize
value can hurt overall system
performance, but it won't hurt OpenLDAP, so you can set a generous
value if you have abundant RAM. If you need to be frugal with your
available RAM, check the See Also section for detailed references on
making finer calculations.
The set_lk_max_locks,
set_lk_max_lockers
, and set_lk_max_objects
set the maximum number of
locks, lockers
, and locked objects
, respectively. If the values
are too small, requests for locks will fail. If the values are too
large, the locking sub-system will use more resources than it really
needs. It's safer to have too much. Run db4.2_stat-c (db_stat -c
in Fedora) in your
database directory to keep tabs on this.
The locking subsystem keeps reads and writes in order. Anything that is writing to the BDB gets an exclusive lock on the object it is writing to. Reads are shared.
Configuring logging will also affect performance. This is what the examples mean:
set_lg_regionmax
The maximum memory cache in bytes for database file name caching. Increase this value as the number of database files increases. Every attribute that you configure for indexing uses one file to store its index, plus id2entry and dn2id which always exist.
set_lg_bsize
The size of the memory cache for logging data, in bytes. When the cache is full, it will be flushed to disk.
set_lg_max
Maximum size of logfile, in bytes. When it reaches the
limit, the file is rotated. This should be a minimum of four
times set_lg_bsize
.
set_lg_dir
Directory for the logfiles. For best performance, store logfiles on a separate disk, or remote network share.
slapd -V
Gives the OpenLDAP server version.
OpenLDAP Performance Tuning:
Getting Started with Berkeley DB:
http://www.oracle.com/technology/documentation/berkeley-db/db/gsg/C/index.html
Chapter 4 of Getting Started with Berkeley DB XML Transaction Processing(http://www.oracle.com/technology/documentation/berkeley-db/xml/gsg_xml_txn/java/blocking_deadlocks.html); see the section, "Locks, Blocks, and Deadlocks"