Choosing a Read-Write Lock Implementation to Use With named
  • 13 May 2020
  • 3 Minutes to read
  • Contributors
  • Dark
  • PDF

Choosing a Read-Write Lock Implementation to Use With named

  • Dark
  • PDF

Since BIND is a multi-threaded application, it uses synchronization primitives - including read-write locks - to govern access to shared data structures. In certain cases, the read-write lock implementation used may affect named performance.

What Does --enable-pthread-rwlock Do?

In BIND 9.15.1, a new ./configure option, --enable-pthread-rwlock, was introduced. This build-time option controls which of the two available read-write lock implementations named will use:

  • internal ISC implementation, or
  • pthreads implementation.

While these two read-write lock flavors can be used interchangeably as they both implement the same internal interface (isc_rwlock_*()), there are subtle differences between them that may have an effect on the server's performance, depending on its workload and the hardware/software versions used.

What Are the Differences Between Read-Write Lock Implementations?

First, it is important to note that:

  • the phrase "ISC read-write locks" refers to the internal ISC implementation available in a given BIND release, and
  • the phrase "pthreads implementation" is a short form of "pthreads implementation on a given platform": glibc has one, BSD systems have a different one, musl libc is different still, etc.

With the above in mind, the two primary differences between internal ISC read-write locks and the glibc implementation of pthreads read-write locks, as of BIND 9.16.3, are:

  • pthreads read-write locks prefer readers over writers; ISC read-write locks generally prefer writers over readers, and
  • pthreads read-write locks do not support upgrading/downgrading a lock being held to a different mode; ISC read-write locks do.

Which Read-Write Lock Implementation Should I Use for My Deployment?

There is no simple answer to this question.

A difference in performance stemming purely from the choice of read-write lock implementation used is only likely to manifest itself on servers handling thousands of queries per second. For lightly loaded servers, switching to a different read-write lock implementation is very unlikely to make a tangible difference.

For performance-sensitive deployments which are subject to higher query loads, it is advised to run comparative tests for both read-write lock flavors on the specific hardware/software platform used, with the expected production query load, and draw conclusions from that.

While carrying out performance tests, it is important to keep track of how many of the responses sent by the tested named instance are error responses (SERVFAIL). In some recursive resolver tests conducted by ISC, named performance appeared to be great in terms of raw response rate, but about 90% of these responses were SERVFAIL responses; for all practical purposes, such a server is not performing "better" than a server which is able to respond at a 10x lower rate but without any errors.

Pay Attention to Hyper-Threading Settings

ISC's own tests carried out for named used as a recursive resolver, with a sample query load, on the hardware we use in our testbed, suggest that hyper-threading settings can significantly affect performance at higher query loads for both read-write lock implementations. Note the emphasis in the previous sentence - this is what the tests we ran suggest, but we cannot be certain that the same conclusion would be reached for different hardware (and/or a different workload).

Our tests for recursive resolvers with a cold cache revealed that:

  • For ISC read-write locks, disabling hyper-threading always improves performance.

  • With hyper-threading disabled, ISC read-write locks perform at least as well as pthreads read-write locks.

  • For the highest tested query rates (> 100,000 queries per second), pthreads read-write locks with hyper-threading enabled seem to be the best-performing choice by far.

Again, please keep in mind that these conclusions might not apply for your hardware/software platform. See GitLab issue #1753 for further information.

Defaults Used in Various BIND Versions

As a result of testing named performance in various deployment scenarios with different source code revisions, the default value for the --enable-pthread-rwlock build-time option was changed twice in early BIND 9.16.x releases. Here is a table summarizing which read-write lock implementation is used by default for a given BIND version if the --enable-pthread-rwlock (or --disable-pthread-rwlock) option is not passed to ./configure:

BIND Version Default Read-Write Lock Implementation
9.16.0 internal ISC implementation
9.16.1 - 9.16.2 pthreads implementation
>= 9.16.3 internal ISC implementation