Commit graph

10 commits

Author SHA1 Message Date
Evan Hunt
e68a691904 add a "qplookups" benchmark test
this loads a file containing DNS names and measures the time it takes to:
1) iterate it,
2) look up each name with dns_qp_getname()
3) look up each name with dns_qp_findname_ancestor()
4) look up a modified name based on the name, to check performance
   when the name is not found.
2023-09-27 16:24:04 -07:00
Tony Finch
06f534fa69
Avoid spurious compilation failures in liburcu headers
When liburcu is not installed from a system package, its headers are
not treated as system headers by the compiler, so BIND's -Werror and
other warning options take effect. The liburcu headers have a lot
of inline functions, some of which do not use all their arguments,
which BIND's build treats as an error.
2023-04-27 12:38:53 +02:00
Tony Finch
4b5ec07bb7 Refactor qp-trie to use QSBR
The first working multi-threaded qp-trie was stuck with an unpleasant
trade-off:

  * Use `isc_rwlock`, which has acceptable write performance, but
    terrible read scalability because the qp-trie made all accesses
    through a single lock.

  * Use `liburcu`, which has great read scalability, but terrible
    write performance, because I was relying on `rcu_synchronize()`
    which is rather slow. And `liburcu` is LGPL.

To get the best of both worlds, we need our own scalable read side,
which we now have with `isc_qsbr`. And we need to modify the write
side so that it is not blocked by readers.

Better write performance requires an async cleanup function like
`call_rcu()`, instead of the blocking `rcu_synchronize()`. (There
is no blocking cleanup in `isc_qsbr`, because I have concluded
that it would be an attractive nuisance.)

Until now, all my multithreading qp-trie designs have been based
around two versions, read-only and mutable. This is too few to
work with asynchronous cleanup. The bare minimum (as in epoch
based reclamation) is three, but it makes more sense to support an
arbitrary number. Doing multi-version support "properly" makes
fewer assumptions about how safe memory reclamation works, and it
makes snapshots and rollbacks simpler.

To avoid making the memory management even more complicated, I
have introduced a new kind of "packed reader node" to anchor the
root of a version of the trie. This is simpler because it re-uses
the existing chunk lifetime logic - see the discussion under
"packed reader nodes" in `qp_p.h`.

I have also made the chunk lifetime logic simpler. The idea of a
"generation" is gone; instead, chunks are either mutable or
immutable. And the QSBR phase number is used to indicate when a
chunk can be reclaimed.

Instead of the `shared_base` flag (which was basically a one-bit
reference count, with a two version limit) the base array now has a
refcount, which replaces the confusing ad-hoc lifetime logic with
something more familiar and systematic.
2023-02-27 13:47:55 +00:00
Tony Finch
a9d57b91db Benchmarks for the qp-trie
The main benchmark is `qpmulti`, which exercizes the qp-trie
transactional API with differing numbers of threads and differing data
sizes, to get some idea of how its performance scales.

The `load-names` benchmark compares the times to populate and query
and the memory used by various BIND data structures: qp-trie, hash
table (chained), hash map (closed), and red-black tree.

The `qp-dump` program is a test utility rather than a benchmark. It
populates a qp-trie and prints it out, either in an ad-hoc text
format, or as input to the graphviz `dot` program.
2023-02-27 13:47:25 +00:00
Ondřej Surý
cfbe01c62f Add microbenchmark for isc_iterated_hash()
Add microbenchmark for isc_iterated_hash() to measure the speed of NSEC3
per second.
2023-01-18 18:32:57 +01:00
Tony Finch
04f3000dfc Fuzzing and benchmarking for dns_name_fromwire()
Since this is very sensitive code which has often had security
problems in many DNS implementations, it needs a decent amount of
validation. This fuzzer ensures that the new code has the same output
as the old code, and that it doesn't take longer than a second.

The benchmark uses the fuzzer's copy of the old dns_name_fromwire()
code to compare a number of scenarios: many compression pointers, many
labels, long labels, random data, with/without downcasing.
2022-11-17 08:45:17 +00:00
Tony Finch
c51fda86ac Delete the render benchmark
Instead of fixing a Coverity complaint (and other style nits),
delete it because it needs input data that can't be generated
with the tools that ship with BIND.
2022-10-21 09:52:40 +00:00
Tony Finch
7ab81eab1c
A couple of compression microbenchmarks
The `render` benchmark loads some binary DNS message dumps and
repeatedly passes them to `dns_message_render`.

The `compress` benchmark loads a list of domain names and packs them
into 4KiB chunks using `dns_name_towire`.
2022-10-17 08:45:44 +02:00
Tony Finch
de10d697ab
A simple siphash benchmark
To see the effect of adding a case-insentitive option.
2022-10-04 10:32:40 +02:00
Tony Finch
68029bfc9d Tests and benchmark for isc_ascii
The test is to verify basic functionality. The benchmark compares a
number of alternative tolower() implementations on large and small
strings.
2022-09-12 12:23:39 +01:00