the djb way

djbdns


tuning the cache

The size of the cache for dnscache is configurable. The default cache size for a service installed by dnscache-conf is 1000000, that is, one million bytes. It may be increased to accomodate the resolver activity on your network, particularly useful when sharing a single dnscache among many hosts.

The envdir utility is used to parameterize the value of CACHESIZE for the dnscache service. To check the current value:

# cd /service/dnscache
# cat env/CACHESIZE
1000000

The envdir utility is also used to parameterize the use of softlimit in the service run script, with the variable DATALIMIT:

# cat env/DATALIMIT
3000000

You can see where this is used in the argument for the -d option to softlimit in the run script:

# cat run
#!/bin/sh
exec 2>&1
exec <seed
exec envdir ./env sh -c '
  exec envuidgid dnscache \
    softlimit -o250 -d "$DATALIMIT" \
      /usr/local/bin/dnscache
'

The difference between DATALIMIT and CACHESIZE is the overhead allowance to run the service under softlimit. In this case, the difference is 2000000. Consider this the "baseline" necessary to run the service, above and beyond the CACHESIZE. In other words, DATALIMIT needs to be set to a value sufficient to accomodate both the CACHESIZE, as well as an additional baseline amount adequate for the binaries and libraries loaded into memory when running the service.

If the dnscache service fails to run at all, it may be that the DATALIMIT parameter is insufficient for your platform. This is entirely possible these days, as the bloat from standard libraries tends to be increasing. Try raising the DATALIMIT in increments of 500000, then restarting the dnscache service --svc -t /service/dnscache-- until the log reports the service is running successfully. Make a note of the new "baseline" for your platform, calculating DATALIMIT minus CACHESIZE.

Now we return to the CACHESIZE. In an ideal world, what you are going for is a CACHESIZE sufficient to accomodate 24 to 72 hours worth of average dnscache activity. To get an idea of the dnscache activity on your server, you can benchmark from the logs:

$ tail /var/multilog/dnscache/current |tai64nlocal

Look for a "stats" line, which (without the time-stamp) will look something like:

stats 362 115206 1 0

The second number (the "115206" here) represents the "cache motion": the number of bytes written to cache since the service started. Make a note of the number, then repeat the next day:

stats 10184 3689712 1 0

In this example the 24-hour difference in cache-motion is 3,574,506, or about 3.5 million bytes cached per day. So, to cache a day's worth of lookups, you would want to increase your CACHESIZE to at least 3500000.

How many days should you try to cache? Most DNS records are set with a time-to-live (TTL) value of between one and three days. (Most of the ./add-* utilities for tinydns set a default TTL value of 86400 seconds, or one day.) When the TTL expires, dnscache needs to look up the record again anyway, so it doesn't do a lot of good to keep more than 3 days of cache.

For this contrived example, then, let's say we want to go for 3 days of cache. We figure that, with 512mb, our server has some memory to burn, and decide to increase the CACHESIZE to 11000000, 11 million bytes:

# cd /service/dnscache
# echo "11000000" > env/CACHESIZE

Don't forget to increase the DATALIMIT accordingly, figured as the new CACHESIZE, plus the "baseline" requirement as discussed above:

# echo "14000000" > env/DATALIMIT

Restart the service to effect the new cache size:

# svc -t /service/dnscache

Check the logs to make sure the service is running ok. Your cache should now be even more efficient, tuned to the activity of your particular network.


Copyright © 2002, 2003, 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.03.09, wcm.