Monday Oct 05, 2009

Link to 13,800,000 entry DS52p6 benchmark yields 17,000 searches per second on x4250

I've posted the results of a Directory Server 5.2 patch 6 benchmark on my wordpress blog. highlights:
  • Sun Netra x4250
  • 13 millions of entries
  • Sun Directory Server 5.2 patch 6
  • ZFS
  • Solaris 10 update 7
  • 17,000 searches per second

Thursday Apr 23, 2009

Implementing a custom LDAP server validator in Struts for SLAMD

Implementing a custom LDAP server validator in the Struts2 framework.[Read More]

Monday Aug 18, 2008

Reference tuning architecture - Directory Server running on small systems

Following is an effective reference tuning architecture for servers with insufficient physical memory to cache the entire Directory Server database in database cache and entry cache(s).

Directory Server uses a single database cache for all entries in the database, that is, db/\*/\*.db3 files, and one entry cache per backend. The database cache is a copy in pages of the .db3 files, the entry cache is essentially a hashmap of entries formatted to return to the LDAP client. The best possible performance occurs when the entry being searched for is in the entry cache and can be returned immediately to the client. The worst possible performance occurs when Directory Server must read a page containing an entry from disk and the page is not in the file system buffer cache.

Referring to the diagram below, when an LDAP client issues a search, Directory Server examines the entry cache for the entry and returns the entry if found. If the entry is not in the entry cache, Directory Server examines the pages in the database cache for the entry. If the entry is found in the database cache, the entry is formatted, placed in the entry cache, and returned to the client. If the entry is neither in the entry cache or the database cache, then Directory Server must issue a disk read to read the page containing the entry - assuming it exists - into the database cache, then format the entry for the entry cache, then return the entry to the client. If the page containing the entry is not in the filesystem buffer cache, then that page must be read from disk.

Dscaching

In some large databases, all entries cannot be cached in database cache and entry cache. When all entries cannot be cached, tuning efforts should concentrate on reducing disk I/O on search operations. This is accomplished by caching the database file pages in the file system buffer cache as follows: set segmap_percent in /etc/system to accommodate the database, reboot the server, and prime the file system cache with dd, set database cache and entry cache sizes to something reasonable, perhaps 2GB each - the database cache size will help with updates. Directory Server response times should be excellent in this scenario. To determine the amount of memory needed for the file system cache, sum the number of bytes in all the db3 files in the database and multiply the result by 1.2 (20%). This is easily done with ls and awk:

ls -l db/\*/\*.db3 | awk '{ total += $5; } END { print total \* 1.2; }'

I/O caused by Directory Server reading data from disk can have a negative impact on Directory Server response times. Not only can response times be elevated, the response times are subject to a greater correlation of variation, i.e., response times are "spiky". The following graph shows the results of a 40 minute test run against Directory Server 5.2 patch 4 under extreme load, with the nsslapd-db-home-directory set to a local filesystem:

Baseline 40Min Spikes

in the diagram above, disk service times on the filesystem containing the mmap backing files averaged above 500 ms.

Change the nsslapd-db-home-directory to a tempfs filesystem, restart Directory Server, and run a new test. After restarting directory server, there will be a short "caching" period as the database cache and entry cache are filled, resulting in:

Beforeprime

The gradual increase in average response times up to about 1000 seconds into the test is the caching period. Immediately afterwards run the same job again and Directory Server begins to respond with very even average response times: this is because there is no I/O on search operations:

Afterprime

Technorati Tags: , , , , ,

Friday May 02, 2008

cache.pl

The following is a perl script that I use to have a quick look at some values in the ldbm database tree. Example usage and output is:
 # ./cache.pl --root /var/opt/sun/ds6 --pwdFile ~/ds6pwd  --bindDN 'cn=dmanager'
localhost 22:23:29 hitratio:99 pagein:560 pageout:561 roevict:0 rwevict:0
localhost 22:23:30 hitratio:99 pagein:560 pageout:561 roevict:0 rwevict:0
localhost 22:23:31 hitratio:99 pagein:560 pageout:561 roevict:0 rwevict:0
localhost 22:23:32 hitratio:99 pagein:560 pageout:561 roevict:0 rwevict:0
The script is very basic and easily extendable.
=== snip ===
#! /usr/bin/perl -w

#
# terry.gardner@sun.com
#
# 08-FEB-2008
#

# Parameter and variables

my ( $lines, $linesPerPage, $loadPerConnection );

#
# set up some default values
#
$port      = 389;
$root      = "/ldap/";
$instance  = "slapd-native";
$delay     = 1;
$hostname  = "localhost";
$pidFile   = $root . "/logs/pid";
$bindDN    = "cn=directory manager";
$pwdFile   = "ds6pwd";
$ldapsearch = "/opt/sun/dsrk6/bin/ldapsearch";
#
# parameters that cannot be modified by
# command line options
#
$dbCacheDN="cn=monitor,cn=ldbm database,cn=plugins,cn=config";

sub displayUsageHints() {
  print "cache.pl prints a tabular display of some directory server\\n";
  print "        operational information.\\n";
  print "\\n";
  print "Usage:\\n";
  print "cache.pl [OPTIONS]\\n";
  print "\\n";
  print "[--hostname hostname]           LDAP server hostname, default: $hostname\\n";
  print "[--port port]                   LDAP server port, default: $port\\n";
  print "[--instance instance]           LDAP server instance, default: $instance\\n";
  print "[--delay delay]                 delay in seconds between samples, default: $delay\\n";
  print "[--pwdFile filename]            file containing the root DN password, default: $pwdFile";
  print "[--bindDN bindDN]               root DN, default $bindDN";
  print "[--ldapsearch ldapsearchBinary] ldapsearch binary, default $ldapsearch";
  print "[--help]                        display ds_monitor.pl command invocation hints\\n";
}

#
# process command line options
#
$sn = 0;
for (@ARGV) {
  if (/--port/) {
    $port = $ARGV[++$sn];
    ++$sn;
  } elsif (/--hostname/) {
    $hostname = $ARGV[++$sn];
    ++$sn;
  } elsif (/--root/) {
    $root = $ARGV[++$sn];
    ++$sn;
  } elsif (/--instance/) {
    $instance = $ARGV[++$sn];
    ++$sn;
  } elsif (/--delay/) {
    $delay = $ARGV[++$sn];
    ++$sn;
  } elsif (/--pidFile/) {
    $pidFile = $ARGV[++$sn];
    ++$sn;
  } elsif (/--pwdFile/) {
    $pwdFile = $ARGV[++$sn];
    ++$sn;
  } elsif (/--bindDN/) {
    $bindDN = $ARGV[++$sn];
    ++$sn;
  } elsif (/--ldapsearch/) {
    $ldapsearch = $ARGV[++$sn];
    ++$sn;
  } elsif (/--help/) {
    &displayUsageHints;
    exit;
  }
}

$scratchFile = "/tmp/" . "cache-" . `date +%H%m%S`;

$lines = 0;
$linesPerPage = 30;

for (;;) {
  # database cache
  $searchBase = $dbCacheDN;
  $cmd = "$ldapsearch -D '$bindDN' -j '$pwdFile' -s base -h $hostname -p $port -b '$searchBase' '(objectClass=\*)'  > $scratchFile";
  `$cmd`;

  open(scratchFile,$scratchFile) || die "Failed to open $scratchFile: $!";

  while ()
  {
    chomp();

    s/://;

    ($attribute,$value) = split(" ",$_,2);

    if (/dbcachehitratio/) {
      $dbcachehitratio = $value;
    } elsif (/dbcachepagein/) {
      $dbcachepagein = $value;
    } elsif (/dbcachepageout/) {
      $dbcachepageout = $value;
    } elsif (/dbcacheroevict/) {
      $dbcacheroevict = $value;
    } elsif (/dbcacherwevict/) {
      $dbcacherwevict = $value;
    }

    $attribute = "";
  }


  close(scratchFile);
  
  # Get the current time
  ($sec,$min,$hour,$junk,$junk,$junk,$junk,$junk,$junk) = localtime(time);

  printf "%9.9s %2.2d:%2.2d:%2.2d hitratio:%d pagein:%d pageout:%d roevict:%d rwevict:%d\\n",
       $hostname,
       $hour,
       $min,
       $sec,
       $dbcachehitratio,
       $dbcachepagein,
       $dbcachepageout,
       $dbcacheroevict,
       $dbcacherwevict;

  sleep $delay;

}
=== snip ===

Friday Dec 07, 2007

GUUG LDAP Conference link

check out the further readings link at the GUUG LDAP Conference.

Technorati Tags: ,

Sunday Nov 25, 2007

Directory Server FAQ - Wiki

There is new content in Directory Server FAQ.

Technorati Tags:

Friday Oct 19, 2007

OpenDS Synchronization

Setting up replication between OpenDS servers is easy. The following example uses the following parameters:
  • directory server & replication server on 10.0.2.1 (replication server port 2389)
  • directory server on 10.0.2.2
  • backend named "userRoot" to be replicated: dc=terrygardner,dc=com
First, read the documentation at the Wiki in order to understand the architecture. Download OpenDS from here. Set up a server on 10.0.2.1 and a server on 10.0.2.2. Setup 10.0.2.1 to be a replication server. On 10.0.2.1, copy the opendsroot/config/replication.ldif file to /tmp/tg-repl.ldif and edit it to look like:

---- snip ----

dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider
objectClass: ds-cfg-multimaster-synchronization-provider
cn: Multimaster Synchronization
ds-cfg-synchronization-provider-enabled: true
ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication

dn: cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: domains

dn: cn=terrygardner,cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-replication-domain-config
cn: terrygardner
ds-cfg-replication-dn: dc=terrygardner,dc=com
ds-cfg-replication-server: 10.0.2.1:2389
ds-cfg-replication-server: 10.0.2.2:2389
ds-cfg-directory-server-id: 2
ds-cfg-receive-status: true

dn: cn=Replication Server,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-replication-server-config
cn: Replication Server
ds-cfg-replication-server-port: 2389
ds-cfg-replication-server: 10.0.2.1:2389
ds-cfg-replication-server-id: 2
---- snip ----

On 10.0.2.2, copy the opendsroot/config/replication.ldif file to /tmp/tg-repl.ldif and edit it to look like:

---- snip ----

dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider
objectClass: ds-cfg-multimaster-synchronization-provider
cn: Multimaster Synchronization
ds-cfg-synchronization-provider-enabled: true
ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication

dn: cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: domains

dn: cn=terrygardner,cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-replication-domain-config
cn: terrygardner
ds-cfg-replication-dn: dc=terrygardner,dc=com
ds-cfg-replication-server: 10.0.2.2:2389
ds-cfg-replication-server: 10.0.2.1:2389
ds-cfg-directory-server-id: 1
ds-cfg-receive-status: true

dn: cn=Replication Server,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-replication-server-config
cn: Replication Server
ds-cfg-replication-server-port: 2389
ds-cfg-replication-server: 10.0.2.1:2389
ds-cfg-replication-server-id: 1
---- snip ----

Note the ds-cfg-replication-server-id attribute.

On 10.0.2.1 and 10.0.2.2, append the /tmp/tg-repl.ldif file onto opendsroot/config/config.ldif, thus:

$ copy opendsroot/config/config.ldif ~/opends-config-orig.ldif && cat /tmp/tg-repl.ldif  >> opendsroot/config/config.ldif
Make an LDIF using opendsroot/bin/make-ldif, and import into 10.0.2.1 and 10.0.2.2 using opends/bin/import/ldif. I created an LDIF with 10 users with this template file:

---- snip ----

define suffix=dc=terrygardner,dc=com
define maildomain=terrygardner.com
define numusers=10

branch: [suffix]

branch: ou=People,[suffix]
subordinateTemplate: person:[numusers]

template: person
rdnAttr: uid
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
givenName: <first>
sn: <last>
cn: {givenName} {sn}
initials: {givenName:1}<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}
employeeNumber: <sequential:0>
uid: user.{employeeNumber}
mail: {uid}@[maildomain]
userPassword: password
telephoneNumber: <random:telephone>
homePhone: <random:telephone>
pager: <random:telephone>
mobile: <random:telephone>
street: <random:numeric:5> <file:streets> Street
l: <file:cities>
st: <file:states>
postalCode: <random:numeric:5>
postalAddress: {cn}${street}${l}, {st}  {postalCode}
description: This is the description for {cn}.
---- snip ----

To create the LDIF file:

$ opendsroot/bin/make-ldif -t /tmp/tg.template -o /tmp/tg.ldif
Import the LDIF:
$ opendsroot/bin/import-ldif -l /tmp/tg.ldif -o userRoot
Start both servers using opendsroot/bin/start-ds. Note: be aware of the values of your JAVA_HOME and JAVA_ARGS environment variables :) Test by modifying something. I usually change the description in the ou=people entry to reflect the replication test date:

---- snip ----

dn: ou=people,dc=terrygardner,dc=com
changetype: modify
replace: description
description: replication test 20-JUN-2007 0916
---- snip ----

The changes will be reflected in the database for 10.0.2.1 and 10.0.2.2. Really simple.

[posted with ecto]
About

Sun, LDAP, SLAMD, DSLA, java, Struts, networking, chess, books, cooking, wine, and many other things.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today