Adding upstream version 2.11.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
6dd69c3878
commit
7ffd64128a
50 changed files with 895 additions and 132 deletions
48
CHANGES
48
CHANGES
|
@ -1,3 +1,51 @@
|
|||
2023-02-08 Jerry Lundström
|
||||
|
||||
Release 2.11.0
|
||||
|
||||
A couple of new features this release courtesy of Petr Špaček
|
||||
@pspacek (ISC) and a bunch of bugfixes.
|
||||
|
||||
First off `dnsperf` can now do verbose statistics during each interval
|
||||
when using `-S`, see long option `verbose-interval-stats`.
|
||||
|
||||
Next is a new latency histogram output using data structures (hg64)
|
||||
created by Tony Finch @fanf2 (ISC), see long option
|
||||
`latency-histogram`. These will also be shown during `-S` when used
|
||||
together with `verbose-interval-stats`.
|
||||
|
||||
Lastly a small change to boolean long options, they no longer require
|
||||
a value (`=yes`) to be enabled.
|
||||
|
||||
Bugfixes:
|
||||
- Make sure the number of outstanding queries don't go negative,
|
||||
happens if queries are timed out before being sent
|
||||
- Fixed #208:
|
||||
- `recv_one()`: Fix handling errno, only store EAGAIN if no other
|
||||
error has been received
|
||||
- `do_recv()`: Don't break on error as it will count it as a received
|
||||
message
|
||||
- Treat `EBADF` as `EAGAIN` for stateful connections, receive thread
|
||||
might read from a closed socket if send thread is reconnecting
|
||||
- `dnsperf`: warn if -c, -T, -q, -Q values are auto-adjusted
|
||||
- Fixed #222: don't process unexpected message if the message is
|
||||
suppressed
|
||||
|
||||
14db835 Opt arg
|
||||
fb81481 Suppress unexpected
|
||||
64b8c6d stats_t initialization
|
||||
8290775 Fix first call to diff_stats
|
||||
4f8bd24 Compile support histograms
|
||||
a9b4f04 External code, latency histograms
|
||||
d1f4b65 add detailed latency histograms
|
||||
044e3a2 data structures for detailed latency histograms
|
||||
ad3fb03 Opt, verbose statistics
|
||||
38bc936 Command usage warnings
|
||||
9f31595 Bad file descriptor
|
||||
d3650eb Receive socket error handling
|
||||
84c8e72 Negative outstanding
|
||||
e7df5e1 Clarify meaning of dnsperf -S output in the man page
|
||||
830eb43 verbose interval stats for dnsperf
|
||||
|
||||
2022-11-11 Jerry Lundström
|
||||
|
||||
Release 2.10.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
@SET_MAKE@
|
||||
|
||||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
|
|
@ -100,7 +100,7 @@ The contrib directory contains additional software related to `dnsperf` and
|
|||
## License
|
||||
|
||||
```
|
||||
Copyright 2019-2022 OARC, Inc.
|
||||
Copyright 2019-2023 OARC, Inc.
|
||||
Copyright 2017-2018 Akamai Technologies
|
||||
Copyright 2006-2016 Nominum, Inc.
|
||||
All rights reserved.
|
||||
|
|
46
configure
vendored
46
configure
vendored
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for dnsperf 2.10.0.
|
||||
# Generated by GNU Autoconf 2.69 for dnsperf 2.11.0.
|
||||
#
|
||||
# Report bugs to <admin@dns-oarc.net>.
|
||||
#
|
||||
|
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='dnsperf'
|
||||
PACKAGE_TARNAME='dnsperf'
|
||||
PACKAGE_VERSION='2.10.0'
|
||||
PACKAGE_STRING='dnsperf 2.10.0'
|
||||
PACKAGE_VERSION='2.11.0'
|
||||
PACKAGE_STRING='dnsperf 2.11.0'
|
||||
PACKAGE_BUGREPORT='admin@dns-oarc.net'
|
||||
PACKAGE_URL='https://github.com/DNS-OARC/dnsperf/issues'
|
||||
|
||||
|
@ -649,6 +649,8 @@ libssl_CFLAGS
|
|||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
HAVE_STDATOMIC_FALSE
|
||||
HAVE_STDATOMIC_TRUE
|
||||
PTHREAD_CFLAGS
|
||||
PTHREAD_LIBS
|
||||
PTHREAD_CC
|
||||
|
@ -1360,7 +1362,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures dnsperf 2.10.0 to adapt to many kinds of systems.
|
||||
\`configure' configures dnsperf 2.11.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1431,7 +1433,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of dnsperf 2.10.0:";;
|
||||
short | recursive ) echo "Configuration of dnsperf 2.11.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1570,7 +1572,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
dnsperf configure 2.10.0
|
||||
dnsperf configure 2.11.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
@ -1939,7 +1941,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by dnsperf $as_me 2.10.0, which was
|
||||
It was created by dnsperf $as_me 2.11.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -2802,7 +2804,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='dnsperf'
|
||||
VERSION='2.10.0'
|
||||
VERSION='2.11.0'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -12891,6 +12893,26 @@ _ACEOF
|
|||
|
||||
fi
|
||||
|
||||
for ac_header in stdatomic.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_stdatomic_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_STDATOMIC_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if test "x$ac_cv_header_stdatomic_h" != "xno"; then
|
||||
HAVE_STDATOMIC_TRUE=
|
||||
HAVE_STDATOMIC_FALSE='#'
|
||||
else
|
||||
HAVE_STDATOMIC_TRUE='#'
|
||||
HAVE_STDATOMIC_FALSE=
|
||||
fi
|
||||
|
||||
|
||||
# Check for OpenSSL
|
||||
|
||||
|
@ -14013,6 +14035,10 @@ if test -z "${ENABLE_GCOV_TRUE}" && test -z "${ENABLE_GCOV_FALSE}"; then
|
|||
as_fn_error $? "conditional \"ENABLE_GCOV\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
if test -z "${HAVE_STDATOMIC_TRUE}" && test -z "${HAVE_STDATOMIC_FALSE}"; then
|
||||
as_fn_error $? "conditional \"HAVE_STDATOMIC\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
|
||||
: "${CONFIG_STATUS=./config.status}"
|
||||
ac_write_fail=0
|
||||
|
@ -14410,7 +14436,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by dnsperf $as_me 2.10.0, which was
|
||||
This file was extended by dnsperf $as_me 2.11.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -14477,7 +14503,7 @@ _ACEOF
|
|||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
dnsperf config.status 2.10.0
|
||||
dnsperf config.status 2.11.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
@ -16,7 +16,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
AC_PREREQ(2.64)
|
||||
AC_INIT([dnsperf], [2.10.0], [admin@dns-oarc.net], [dnsperf], [https://github.com/DNS-OARC/dnsperf/issues])
|
||||
AC_INIT([dnsperf], [2.11.0], [admin@dns-oarc.net], [dnsperf], [https://github.com/DNS-OARC/dnsperf/issues])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||
AC_CONFIG_SRCDIR([src/dnsperf.c])
|
||||
AC_CONFIG_HEADER([src/config.h])
|
||||
|
@ -56,6 +56,8 @@ AM_EXTRA_RECURSIVE_TARGETS([gcov])
|
|||
# Checks for support.
|
||||
AX_PTHREAD
|
||||
AC_CHECK_LIB([m], [sqrt])
|
||||
AC_CHECK_HEADERS([stdatomic.h])
|
||||
AM_CONDITIONAL([HAVE_STDATOMIC], [test "x$ac_cv_header_stdatomic_h" != "xno"])
|
||||
|
||||
# Check for OpenSSL
|
||||
PKG_CHECK_MODULES([libssl], [libssl])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Copyright 2019-2022 OARC, Inc.
|
||||
.\" Copyright 2019-2023 OARC, Inc.
|
||||
.\" Copyright 2017-2018 Akamai Technologies
|
||||
.\" Copyright 2006-2016 Nominum, Inc.
|
||||
.\" All rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
@ -30,9 +30,15 @@ bin_PROGRAMS = dnsperf resperf
|
|||
dist_bin_SCRIPTS = resperf-report
|
||||
|
||||
_libperf_sources = datafile.c dns.c log.c net.c opt.c os.c strerror.c qtype.c \
|
||||
edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c parse_uri.c
|
||||
edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c ext/parse_uri.c
|
||||
|
||||
_libperf_headers = datafile.h dns.h log.h net.h opt.h os.h util.h strerror.h \
|
||||
list.h result.h buffer.h qtype.h edns.h tsig.h parse_uri.h
|
||||
list.h result.h buffer.h qtype.h edns.h tsig.h ext/parse_uri.h
|
||||
|
||||
if HAVE_STDATOMIC
|
||||
_libperf_sources += ext/hg64.c
|
||||
_libperf_headers += ext/hg64.h
|
||||
endif
|
||||
|
||||
dnsperf_SOURCES = $(_libperf_sources) dnsperf.c
|
||||
dist_dnsperf_SOURCES = $(_libperf_headers)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
@SET_MAKE@
|
||||
|
||||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
@ -107,6 +107,8 @@ POST_UNINSTALL = :
|
|||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = dnsperf$(EXEEXT) resperf$(EXEEXT)
|
||||
@HAVE_STDATOMIC_TRUE@am__append_1 = ext/hg64.c
|
||||
@HAVE_STDATOMIC_TRUE@am__append_2 = ext/hg64.h
|
||||
subdir = src
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_append_flag.m4 \
|
||||
|
@ -127,14 +129,23 @@ CONFIG_CLEAN_VPATH_FILES =
|
|||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \
|
||||
"$(DESTDIR)$(man1dir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am__objects_1 = datafile.$(OBJEXT) dns.$(OBJEXT) log.$(OBJEXT) \
|
||||
am__dnsperf_SOURCES_DIST = datafile.c dns.c log.c net.c opt.c os.c \
|
||||
strerror.c qtype.c edns.c tsig.c net_udp.c net_tcp.c net_dot.c \
|
||||
net_doh.c ext/parse_uri.c ext/hg64.c dnsperf.c
|
||||
am__dirstamp = $(am__leading_dot)dirstamp
|
||||
@HAVE_STDATOMIC_TRUE@am__objects_1 = ext/hg64.$(OBJEXT)
|
||||
am__objects_2 = datafile.$(OBJEXT) dns.$(OBJEXT) log.$(OBJEXT) \
|
||||
net.$(OBJEXT) opt.$(OBJEXT) os.$(OBJEXT) strerror.$(OBJEXT) \
|
||||
qtype.$(OBJEXT) edns.$(OBJEXT) tsig.$(OBJEXT) \
|
||||
net_udp.$(OBJEXT) net_tcp.$(OBJEXT) net_dot.$(OBJEXT) \
|
||||
net_doh.$(OBJEXT) parse_uri.$(OBJEXT)
|
||||
am_dnsperf_OBJECTS = $(am__objects_1) dnsperf.$(OBJEXT)
|
||||
am__objects_2 =
|
||||
dist_dnsperf_OBJECTS = $(am__objects_2)
|
||||
net_doh.$(OBJEXT) ext/parse_uri.$(OBJEXT) $(am__objects_1)
|
||||
am_dnsperf_OBJECTS = $(am__objects_2) dnsperf.$(OBJEXT)
|
||||
am__dist_dnsperf_SOURCES_DIST = datafile.h dns.h log.h net.h opt.h \
|
||||
os.h util.h strerror.h list.h result.h buffer.h qtype.h edns.h \
|
||||
tsig.h ext/parse_uri.h ext/hg64.h
|
||||
am__objects_3 =
|
||||
am__objects_4 = $(am__objects_3)
|
||||
dist_dnsperf_OBJECTS = $(am__objects_4)
|
||||
dnsperf_OBJECTS = $(am_dnsperf_OBJECTS) $(dist_dnsperf_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
dnsperf_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
|
@ -144,8 +155,14 @@ AM_V_lt = $(am__v_lt_@AM_V@)
|
|||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
am_resperf_OBJECTS = $(am__objects_1) resperf.$(OBJEXT)
|
||||
dist_resperf_OBJECTS = $(am__objects_2)
|
||||
am__resperf_SOURCES_DIST = datafile.c dns.c log.c net.c opt.c os.c \
|
||||
strerror.c qtype.c edns.c tsig.c net_udp.c net_tcp.c net_dot.c \
|
||||
net_doh.c ext/parse_uri.c ext/hg64.c resperf.c
|
||||
am_resperf_OBJECTS = $(am__objects_2) resperf.$(OBJEXT)
|
||||
am__dist_resperf_SOURCES_DIST = datafile.h dns.h log.h net.h opt.h \
|
||||
os.h util.h strerror.h list.h result.h buffer.h qtype.h edns.h \
|
||||
tsig.h ext/parse_uri.h ext/hg64.h
|
||||
dist_resperf_OBJECTS = $(am__objects_4)
|
||||
resperf_OBJECTS = $(am_resperf_OBJECTS) $(dist_resperf_OBJECTS)
|
||||
resperf_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
|
@ -198,9 +215,9 @@ am__depfiles_remade = ./$(DEPDIR)/datafile.Po ./$(DEPDIR)/dns.Po \
|
|||
./$(DEPDIR)/net.Po ./$(DEPDIR)/net_doh.Po \
|
||||
./$(DEPDIR)/net_dot.Po ./$(DEPDIR)/net_tcp.Po \
|
||||
./$(DEPDIR)/net_udp.Po ./$(DEPDIR)/opt.Po ./$(DEPDIR)/os.Po \
|
||||
./$(DEPDIR)/parse_uri.Po ./$(DEPDIR)/qtype.Po \
|
||||
./$(DEPDIR)/resperf.Po ./$(DEPDIR)/strerror.Po \
|
||||
./$(DEPDIR)/tsig.Po
|
||||
./$(DEPDIR)/qtype.Po ./$(DEPDIR)/resperf.Po \
|
||||
./$(DEPDIR)/strerror.Po ./$(DEPDIR)/tsig.Po \
|
||||
ext/$(DEPDIR)/hg64.Po ext/$(DEPDIR)/parse_uri.Po
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
|
@ -222,8 +239,9 @@ am__v_CCLD_0 = @echo " CCLD " $@;
|
|||
am__v_CCLD_1 =
|
||||
SOURCES = $(dnsperf_SOURCES) $(dist_dnsperf_SOURCES) \
|
||||
$(resperf_SOURCES) $(dist_resperf_SOURCES)
|
||||
DIST_SOURCES = $(dnsperf_SOURCES) $(dist_dnsperf_SOURCES) \
|
||||
$(resperf_SOURCES) $(dist_resperf_SOURCES)
|
||||
DIST_SOURCES = $(am__dnsperf_SOURCES_DIST) \
|
||||
$(am__dist_dnsperf_SOURCES_DIST) $(am__resperf_SOURCES_DIST) \
|
||||
$(am__dist_resperf_SOURCES_DIST)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
|
@ -440,12 +458,12 @@ AM_CFLAGS = -I$(srcdir) \
|
|||
|
||||
EXTRA_DIST = dnsperf.1.in resperf-report resperf.1.in
|
||||
dist_bin_SCRIPTS = resperf-report
|
||||
_libperf_sources = datafile.c dns.c log.c net.c opt.c os.c strerror.c qtype.c \
|
||||
edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c parse_uri.c
|
||||
|
||||
_libperf_headers = datafile.h dns.h log.h net.h opt.h os.h util.h strerror.h \
|
||||
list.h result.h buffer.h qtype.h edns.h tsig.h parse_uri.h
|
||||
|
||||
_libperf_sources = datafile.c dns.c log.c net.c opt.c os.c strerror.c \
|
||||
qtype.c edns.c tsig.c net_udp.c net_tcp.c net_dot.c net_doh.c \
|
||||
ext/parse_uri.c $(am__append_1)
|
||||
_libperf_headers = datafile.h dns.h log.h net.h opt.h os.h util.h \
|
||||
strerror.h list.h result.h buffer.h qtype.h edns.h tsig.h \
|
||||
ext/parse_uri.h $(am__append_2)
|
||||
dnsperf_SOURCES = $(_libperf_sources) dnsperf.c
|
||||
dist_dnsperf_SOURCES = $(_libperf_headers)
|
||||
dnsperf_LDADD = $(PTHREAD_LIBS) $(libssl_LIBS) $(libcrypto_LIBS) \
|
||||
|
@ -555,6 +573,15 @@ clean-binPROGRAMS:
|
|||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
ext/$(am__dirstamp):
|
||||
@$(MKDIR_P) ext
|
||||
@: > ext/$(am__dirstamp)
|
||||
ext/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) ext/$(DEPDIR)
|
||||
@: > ext/$(DEPDIR)/$(am__dirstamp)
|
||||
ext/parse_uri.$(OBJEXT): ext/$(am__dirstamp) \
|
||||
ext/$(DEPDIR)/$(am__dirstamp)
|
||||
ext/hg64.$(OBJEXT): ext/$(am__dirstamp) ext/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
dnsperf$(EXEEXT): $(dnsperf_OBJECTS) $(dnsperf_DEPENDENCIES) $(EXTRA_dnsperf_DEPENDENCIES)
|
||||
@rm -f dnsperf$(EXEEXT)
|
||||
|
@ -601,6 +628,7 @@ uninstall-dist_binSCRIPTS:
|
|||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
-rm -f ext/*.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
@ -617,11 +645,12 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_udp.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_uri.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qtype.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resperf.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@ext/$(DEPDIR)/hg64.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@ext/$(DEPDIR)/parse_uri.Po@am__quote@ # am--include-marker
|
||||
|
||||
$(am__depfiles_remade):
|
||||
@$(MKDIR_P) $(@D)
|
||||
|
@ -893,6 +922,8 @@ clean-generic:
|
|||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
-rm -f ext/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f ext/$(am__dirstamp)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
|
@ -916,11 +947,12 @@ distclean: distclean-recursive
|
|||
-rm -f ./$(DEPDIR)/net_udp.Po
|
||||
-rm -f ./$(DEPDIR)/opt.Po
|
||||
-rm -f ./$(DEPDIR)/os.Po
|
||||
-rm -f ./$(DEPDIR)/parse_uri.Po
|
||||
-rm -f ./$(DEPDIR)/qtype.Po
|
||||
-rm -f ./$(DEPDIR)/resperf.Po
|
||||
-rm -f ./$(DEPDIR)/strerror.Po
|
||||
-rm -f ./$(DEPDIR)/tsig.Po
|
||||
-rm -f ext/$(DEPDIR)/hg64.Po
|
||||
-rm -f ext/$(DEPDIR)/parse_uri.Po
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-hdr distclean-tags
|
||||
|
@ -982,11 +1014,12 @@ maintainer-clean: maintainer-clean-recursive
|
|||
-rm -f ./$(DEPDIR)/net_udp.Po
|
||||
-rm -f ./$(DEPDIR)/opt.Po
|
||||
-rm -f ./$(DEPDIR)/os.Po
|
||||
-rm -f ./$(DEPDIR)/parse_uri.Po
|
||||
-rm -f ./$(DEPDIR)/qtype.Po
|
||||
-rm -f ./$(DEPDIR)/resperf.Po
|
||||
-rm -f ./$(DEPDIR)/strerror.Po
|
||||
-rm -f ./$(DEPDIR)/tsig.Po
|
||||
-rm -f ext/$(DEPDIR)/hg64.Po
|
||||
-rm -f ext/$(DEPDIR)/parse_uri.Po
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
||||
#undef HAVE_STDATOMIC_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Copyright 2019-2022 OARC, Inc.
|
||||
.\" Copyright 2019-2023 OARC, Inc.
|
||||
.\" Copyright 2017-2018 Akamai Technologies
|
||||
.\" Copyright 2006-2016 Nominum, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -341,8 +341,9 @@ The default is the loopback address, 127.0.0.1.
|
|||
\fB-S \fIstats_interval\fR
|
||||
.br
|
||||
.RS
|
||||
If this parameter is specified, a count of the number of queries per second
|
||||
during the interval will be printed out every stats_interval seconds.
|
||||
If this parameter is specified, a count of the number of answers received
|
||||
per second during the interval will be printed out every \fIstats_interval\fR
|
||||
seconds.
|
||||
.RE
|
||||
|
||||
\fB-t \fItimeout\fR
|
||||
|
@ -458,7 +459,6 @@ Following type are available.
|
|||
.br
|
||||
\fBunexpected\fR: Suppress messages about answers with an unexpected message ID
|
||||
.RE
|
||||
|
||||
\fBnum-queries-per-conn=\fINUMBER\fR
|
||||
.br
|
||||
.RS
|
||||
|
@ -474,6 +474,29 @@ Waiting for responses may timeout and the timeout used for this is the
|
|||
same as specified by \fB-t\fR.
|
||||
Note that this option is only useful for connection oriented protocols.
|
||||
.RE
|
||||
|
||||
\fBverbose-interval-stats\fR
|
||||
.br
|
||||
.RS
|
||||
Change the statistics format of \fB-S\fR to that shown at end of run.
|
||||
|
||||
\fIPlease note\fR: Min/max values for latency and connections are not
|
||||
available in interval statistics.
|
||||
Number of answers received within \fIstats_interval\fR can legitimately
|
||||
exceed number of queries sent, depending on answer latency, configured
|
||||
\fItimeout\fR, and \fIstats_interval\fR.
|
||||
.RE
|
||||
|
||||
\fBlatency-histogram\fR
|
||||
.br
|
||||
.RS
|
||||
Print detailed latency histograms for DNS answers and connections.
|
||||
Latency is quantized into bins with roughly 3 % resolution, and latency
|
||||
range for individual bins increases logarithmically.
|
||||
This is done to to limit amount of memory required for histograms
|
||||
and also allows to visualize latency using logarithmic percentile histograms
|
||||
with minimal postprocessing.
|
||||
.RE
|
||||
.SH "SEE ALSO"
|
||||
\fBresperf\fR(1)
|
||||
.SH AUTHOR
|
||||
|
|
264
src/dnsperf.c
264
src/dnsperf.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -32,6 +32,10 @@
|
|||
#include "util.h"
|
||||
#include "list.h"
|
||||
#include "buffer.h"
|
||||
#if HAVE_STDATOMIC_H
|
||||
#include "ext/hg64.h"
|
||||
#define USE_HISTOGRAMS
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
|
@ -49,6 +53,8 @@
|
|||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define HISTOGRAM_SIGBITS 5 /* about 3 % latency precision */
|
||||
|
||||
#define DEFAULT_SERVER_NAME "127.0.0.1"
|
||||
#define DEFAULT_SERVER_PORT 53
|
||||
#define DEFAULT_SERVER_DOT_PORT 853
|
||||
|
@ -85,6 +91,7 @@ typedef struct {
|
|||
uint32_t max_outstanding;
|
||||
uint32_t max_qps;
|
||||
uint64_t stats_interval;
|
||||
bool verbose_interval_stats;
|
||||
bool updates;
|
||||
bool binary_input;
|
||||
perf_input_format_t input_format;
|
||||
|
@ -92,6 +99,9 @@ typedef struct {
|
|||
enum perf_net_mode mode;
|
||||
perf_suppress_t suppress;
|
||||
size_t num_queries_per_conn;
|
||||
#ifdef USE_HISTOGRAMS
|
||||
bool latency_histogram;
|
||||
#endif
|
||||
} config_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -101,8 +111,9 @@ typedef struct {
|
|||
struct timespec stop_time_ns;
|
||||
} times_t;
|
||||
|
||||
#define DNSPERF_STATS_RCODECOUNTS 16
|
||||
typedef struct {
|
||||
uint64_t rcodecounts[16];
|
||||
uint64_t rcodecounts[DNSPERF_STATS_RCODECOUNTS];
|
||||
|
||||
uint64_t num_sent;
|
||||
uint64_t num_interrupted;
|
||||
|
@ -124,6 +135,11 @@ typedef struct {
|
|||
uint64_t conn_latency_sum_squares;
|
||||
uint64_t conn_latency_min;
|
||||
uint64_t conn_latency_max;
|
||||
|
||||
#ifdef USE_HISTOGRAMS
|
||||
hg64* latency;
|
||||
hg64* conn_latency;
|
||||
#endif
|
||||
} stats_t;
|
||||
|
||||
typedef perf_list(struct query_info) query_list;
|
||||
|
@ -257,7 +273,86 @@ stddev(uint64_t sum_of_squares, uint64_t sum, uint64_t total)
|
|||
}
|
||||
|
||||
static void
|
||||
print_statistics(const config_t* config, const times_t* times, stats_t* stats)
|
||||
diff_stats(const config_t* config, stats_t* last, stats_t* now, stats_t* diff)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < DNSPERF_STATS_RCODECOUNTS; i++) {
|
||||
diff->rcodecounts[i] = now->rcodecounts[i] - last->rcodecounts[i];
|
||||
}
|
||||
|
||||
diff->num_sent = now->num_sent - last->num_sent;
|
||||
diff->num_interrupted = now->num_interrupted - last->num_interrupted;
|
||||
diff->num_timedout = now->num_timedout - last->num_timedout;
|
||||
diff->num_completed = now->num_completed - last->num_completed;
|
||||
|
||||
diff->total_request_size = now->total_request_size - last->total_request_size;
|
||||
diff->total_response_size = now->total_response_size - last->total_response_size;
|
||||
|
||||
diff->latency_sum = now->latency_sum - last->latency_sum;
|
||||
diff->latency_sum_squares = now->latency_sum_squares - last->latency_sum_squares;
|
||||
diff->latency_min = 0; /* not enough data */
|
||||
diff->latency_max = 0;
|
||||
|
||||
diff->num_conn_reconnect = now->num_conn_reconnect - last->num_conn_reconnect;
|
||||
diff->num_conn_completed = now->num_conn_completed - last->num_conn_completed;
|
||||
|
||||
diff->conn_latency_sum = now->conn_latency_sum - last->conn_latency_sum;
|
||||
diff->conn_latency_sum_squares = now->conn_latency_sum_squares - last->conn_latency_sum_squares;
|
||||
diff->conn_latency_min = 0;
|
||||
diff->conn_latency_max = 0;
|
||||
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram) {
|
||||
free(diff->latency);
|
||||
diff->latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
if (last->latency) {
|
||||
hg64_diff(now->latency, last->latency, diff->latency);
|
||||
} else { /* first sample */
|
||||
hg64_merge(diff->latency, now->latency);
|
||||
}
|
||||
hg64_get(diff->latency, hg64_min_key(diff->latency), &diff->latency_min, NULL, NULL);
|
||||
hg64_get(diff->latency, hg64_max_key(diff->latency), NULL, &diff->latency_max, NULL);
|
||||
|
||||
free(diff->conn_latency);
|
||||
diff->conn_latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
if (last->conn_latency) {
|
||||
hg64_diff(now->conn_latency, last->conn_latency, diff->conn_latency);
|
||||
} else { /* first sample */
|
||||
hg64_merge(diff->conn_latency, now->conn_latency);
|
||||
}
|
||||
hg64_get(diff->conn_latency, hg64_min_key(diff->conn_latency), &diff->conn_latency_min, NULL, NULL);
|
||||
hg64_get(diff->conn_latency, hg64_max_key(diff->conn_latency), NULL, &diff->conn_latency_max, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_HISTOGRAMS
|
||||
static void
|
||||
print_histogram(hg64* histogram, const char* const desc)
|
||||
{
|
||||
printf(" Latency bucket (s): %s\n", desc);
|
||||
uint64_t pmin, pmax, pcount;
|
||||
for (unsigned key = 0;
|
||||
hg64_get(histogram, key, &pmin, &pmax, &pcount) == true;
|
||||
key = hg64_next(histogram, key)) {
|
||||
if (pcount == 0)
|
||||
continue;
|
||||
printf(" %" PRIu64 ".%06" PRIu64 " - %" PRIu64 ".%06" PRIu64 ": %" PRIu64 "\n",
|
||||
pmin / MILLION,
|
||||
pmin % MILLION,
|
||||
pmax / MILLION,
|
||||
pmax % MILLION,
|
||||
pcount);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now != 0 is call to print stats in the middle of test run.
|
||||
* min-max values are not available on per-interval basis, so skip them.
|
||||
*/
|
||||
static void
|
||||
print_statistics(const config_t* config, const times_t* times, stats_t* stats, uint64_t now, uint64_t interval_time)
|
||||
{
|
||||
const char* units;
|
||||
uint64_t run_time;
|
||||
|
@ -267,9 +362,12 @@ print_statistics(const config_t* config, const times_t* times, stats_t* stats)
|
|||
|
||||
units = config->updates ? "Updates" : "Queries";
|
||||
|
||||
run_time = times->end_time - times->start_time;
|
||||
if (now)
|
||||
run_time = now - times->start_time;
|
||||
else
|
||||
run_time = times->end_time - times->start_time;
|
||||
|
||||
printf("Statistics:\n\n");
|
||||
printf("%sStatistics:\n\n", now ? "Interval " : "");
|
||||
|
||||
printf(" %s sent: %" PRIu64 "\n",
|
||||
units, stats->num_sent);
|
||||
|
@ -287,7 +385,7 @@ print_statistics(const config_t* config, const times_t* times, stats_t* stats)
|
|||
|
||||
printf(" Response codes: ");
|
||||
first_rcode = true;
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < DNSPERF_STATS_RCODECOUNTS; i++) {
|
||||
if (stats->rcodecounts[i] == 0)
|
||||
continue;
|
||||
if (first_rcode)
|
||||
|
@ -308,23 +406,33 @@ print_statistics(const config_t* config, const times_t* times, stats_t* stats)
|
|||
(unsigned int)(run_time / MILLION),
|
||||
(unsigned int)(run_time % MILLION));
|
||||
printf(" %s per second: %.6lf\n", units,
|
||||
PERF_SAFE_DIV(stats->num_completed, (((double)run_time) / MILLION)));
|
||||
PERF_SAFE_DIV(stats->num_completed, (((double)(now ? interval_time : run_time) / MILLION))));
|
||||
|
||||
printf("\n");
|
||||
|
||||
latency_avg = PERF_SAFE_DIV(stats->latency_sum, stats->num_completed);
|
||||
printf(" Average Latency (s): %u.%06u (min %u.%06u, max %u.%06u)\n",
|
||||
printf(" Average Latency (s): %u.%06u",
|
||||
(unsigned int)(latency_avg / MILLION),
|
||||
(unsigned int)(latency_avg % MILLION),
|
||||
(unsigned int)(stats->latency_min / MILLION),
|
||||
(unsigned int)(stats->latency_min % MILLION),
|
||||
(unsigned int)(stats->latency_max / MILLION),
|
||||
(unsigned int)(stats->latency_max % MILLION));
|
||||
(unsigned int)(latency_avg % MILLION));
|
||||
if (!now) {
|
||||
printf(" (min %u.%06u, max %u.%06u)\n",
|
||||
(unsigned int)(stats->latency_min / MILLION),
|
||||
(unsigned int)(stats->latency_min % MILLION),
|
||||
(unsigned int)(stats->latency_max / MILLION),
|
||||
(unsigned int)(stats->latency_max % MILLION));
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (stats->num_completed > 1) {
|
||||
printf(" Latency StdDev (s): %f\n",
|
||||
stddev(stats->latency_sum_squares, stats->latency_sum,
|
||||
stats->num_completed)
|
||||
/ MILLION);
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram)
|
||||
print_histogram(stats->latency, "answer count");
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
@ -336,32 +444,56 @@ print_statistics(const config_t* config, const times_t* times, stats_t* stats)
|
|||
printf("Connection Statistics:\n\n");
|
||||
printf(" Reconnections: %" PRIu64 "\n\n", stats->num_conn_reconnect);
|
||||
latency_avg = PERF_SAFE_DIV(stats->conn_latency_sum, stats->num_conn_completed);
|
||||
printf(" Average Latency (s): %u.%06u (min %u.%06u, max %u.%06u)\n",
|
||||
printf(" Average Latency (s): %u.%06u",
|
||||
(unsigned int)(latency_avg / MILLION),
|
||||
(unsigned int)(latency_avg % MILLION),
|
||||
(unsigned int)(stats->conn_latency_min / MILLION),
|
||||
(unsigned int)(stats->conn_latency_min % MILLION),
|
||||
(unsigned int)(stats->conn_latency_max / MILLION),
|
||||
(unsigned int)(stats->conn_latency_max % MILLION));
|
||||
(unsigned int)(latency_avg % MILLION));
|
||||
if (!now) {
|
||||
printf(" (min %u.%06u, max %u.%06u)\n",
|
||||
(unsigned int)(stats->conn_latency_min / MILLION),
|
||||
(unsigned int)(stats->conn_latency_min % MILLION),
|
||||
(unsigned int)(stats->conn_latency_max / MILLION),
|
||||
(unsigned int)(stats->conn_latency_max % MILLION));
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
if (stats->num_conn_completed > 1) {
|
||||
printf(" Latency StdDev (s): %f\n",
|
||||
stddev(stats->conn_latency_sum_squares, stats->conn_latency_sum, stats->num_conn_completed) / MILLION);
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram)
|
||||
print_histogram(stats->latency, "connection count");
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must free() stats->latency and stats->conn_latency.
|
||||
*/
|
||||
static void
|
||||
sum_stats(const config_t* config, stats_t* total)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
memset(total, 0, sizeof(*total));
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram) {
|
||||
total->latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
total->conn_latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < config->threads; i++) {
|
||||
stats_t* stats = &threads[i].stats;
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram) {
|
||||
hg64_merge(total->latency, stats->latency);
|
||||
hg64_merge(total->conn_latency, stats->conn_latency);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
for (j = 0; j < DNSPERF_STATS_RCODECOUNTS; j++)
|
||||
total->rcodecounts[j] += stats->rcodecounts[j];
|
||||
|
||||
total->num_sent += stats->num_sent;
|
||||
|
@ -499,6 +631,12 @@ setup(int argc, char** argv, config_t* config)
|
|||
"suppress messages/warnings, see man-page for list of message types", NULL, &local_suppress);
|
||||
perf_long_opt_add("num-queries-per-conn", perf_opt_uint, "queries",
|
||||
"Number of queries to send per connection", NULL, &config->num_queries_per_conn);
|
||||
perf_long_opt_add("verbose-interval-stats", perf_opt_boolean, NULL,
|
||||
"print detailed statistics for each stats_interval", NULL, &config->verbose_interval_stats);
|
||||
#ifdef USE_HISTOGRAMS
|
||||
perf_long_opt_add("latency-histogram", perf_opt_boolean, NULL,
|
||||
"collect and print detailed latency histograms", NULL, &config->latency_histogram);
|
||||
#endif
|
||||
|
||||
bool log_stdout = false;
|
||||
perf_opt_add('W', perf_opt_boolean, NULL, "log warnings and errors to stdout instead of stderr", NULL, &log_stdout);
|
||||
|
@ -574,14 +712,18 @@ setup(int argc, char** argv, config_t* config)
|
|||
* If we run more threads than max-qps, some threads will have
|
||||
* ->max_qps set to 0, and be unlimited.
|
||||
*/
|
||||
if (config->max_qps > 0 && config->threads > config->max_qps)
|
||||
if (config->max_qps > 0 && config->threads > config->max_qps) {
|
||||
perf_log_warning("requested max QPS limit (-Q %u) is lower than number of threads (-T %u), lowering number of threads", config->max_qps, config->threads);
|
||||
config->threads = config->max_qps;
|
||||
}
|
||||
|
||||
/*
|
||||
* We also can't run more threads than clients.
|
||||
*/
|
||||
if (config->threads > config->clients)
|
||||
if (config->threads > config->clients) {
|
||||
perf_log_warning("requested number of threads (-T %u) exceeds number of clients (-c %u), lowering number of threads\n", config->threads, config->clients);
|
||||
config->threads = config->clients;
|
||||
}
|
||||
|
||||
#ifndef HAVE_LDNS
|
||||
if (config->updates) {
|
||||
|
@ -636,6 +778,10 @@ query_move(threadinfo_t* tinfo, query_info* q, query_move_op op)
|
|||
static inline uint64_t
|
||||
num_outstanding(const stats_t* stats)
|
||||
{
|
||||
/* make sure negative values aren't returned */
|
||||
if (stats->num_completed + stats->num_timedout > stats->num_sent) {
|
||||
return 0;
|
||||
}
|
||||
return stats->num_sent - stats->num_completed - stats->num_timedout;
|
||||
}
|
||||
|
||||
|
@ -920,7 +1066,10 @@ recv_one(threadinfo_t* tinfo, int which_sock,
|
|||
}
|
||||
if (!n) {
|
||||
// Treat connection closed like try again until reconnection features are in
|
||||
*saved_errnop = EAGAIN;
|
||||
if (!*saved_errnop) {
|
||||
// only set this if there was no error before to allow above error check to overwrite EAGAIN
|
||||
*saved_errnop = EAGAIN;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
recvd->sock = tinfo->socks[which_sock];
|
||||
|
@ -1006,8 +1155,6 @@ do_recv(void* arg)
|
|||
break;
|
||||
}
|
||||
bit_set(socketbits, current_socket);
|
||||
if (saved_errno != EAGAIN)
|
||||
break;
|
||||
}
|
||||
if (j == tinfo->nsocks)
|
||||
break;
|
||||
|
@ -1039,11 +1186,13 @@ do_recv(void* arg)
|
|||
perf_log_warning("received short response");
|
||||
continue;
|
||||
}
|
||||
if (recvd[i].unexpected && !tinfo->config->suppress.unexpected) {
|
||||
perf_log_warning("received a response with an "
|
||||
"unexpected (maybe timed out) "
|
||||
"id: %u",
|
||||
recvd[i].qid);
|
||||
if (recvd[i].unexpected) {
|
||||
if (!tinfo->config->suppress.unexpected) {
|
||||
perf_log_warning("received a response with an "
|
||||
"unexpected (maybe timed out) "
|
||||
"id: %u",
|
||||
recvd[i].qid);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
latency = recvd[i].when - recvd[i].sent;
|
||||
|
@ -1061,6 +1210,11 @@ do_recv(void* arg)
|
|||
stats->total_response_size += recvd[i].size;
|
||||
stats->rcodecounts[recvd[i].rcode]++;
|
||||
stats->latency_sum += latency;
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (stats->latency) {
|
||||
hg64_inc(stats->latency, latency);
|
||||
}
|
||||
#endif
|
||||
stats->latency_sum_squares += (latency * latency);
|
||||
if (latency < stats->latency_min || stats->num_completed == 1)
|
||||
stats->latency_min = latency;
|
||||
|
@ -1097,18 +1251,17 @@ static void*
|
|||
do_interval_stats(void* arg)
|
||||
{
|
||||
threadinfo_t* tinfo;
|
||||
stats_t total;
|
||||
stats_t total = {};
|
||||
stats_t last = {};
|
||||
stats_t diff = {};
|
||||
uint64_t now;
|
||||
uint64_t last_interval_time;
|
||||
uint64_t last_completed;
|
||||
uint64_t interval_time;
|
||||
uint64_t num_completed;
|
||||
double qps;
|
||||
struct perf_net_socket sock = { .mode = sock_pipe, .fd = threadpipe[0] };
|
||||
|
||||
tinfo = arg;
|
||||
last_interval_time = tinfo->times->start_time;
|
||||
last_completed = 0;
|
||||
|
||||
wait_for_start();
|
||||
while (perf_os_waituntilreadable(&sock, threadpipe[0],
|
||||
|
@ -1117,13 +1270,23 @@ do_interval_stats(void* arg)
|
|||
now = perf_get_time();
|
||||
sum_stats(tinfo->config, &total);
|
||||
interval_time = now - last_interval_time;
|
||||
num_completed = total.num_completed - last_completed;
|
||||
qps = num_completed / (((double)interval_time) / MILLION);
|
||||
perf_log_printf("%u.%06u: %.6lf",
|
||||
(unsigned int)(now / MILLION),
|
||||
(unsigned int)(now % MILLION), qps);
|
||||
|
||||
if (tinfo->config->verbose_interval_stats) {
|
||||
diff_stats(tinfo->config, &last, &total, &diff);
|
||||
print_statistics(tinfo->config, tinfo->times, &diff, now, interval_time);
|
||||
} else {
|
||||
qps = (total.num_completed - last.num_completed) / (((double)interval_time) / MILLION);
|
||||
perf_log_printf("%u.%06u: %.6lf",
|
||||
(unsigned int)(now / MILLION),
|
||||
(unsigned int)(now % MILLION), qps);
|
||||
}
|
||||
|
||||
last_interval_time = now;
|
||||
last_completed = total.num_completed;
|
||||
#ifdef USE_HISTOGRAMS
|
||||
free(last.latency);
|
||||
free(last.conn_latency);
|
||||
#endif
|
||||
last = total;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1189,6 +1352,11 @@ static void perf__net_event(struct perf_net_socket* sock, perf_socket_event_t ev
|
|||
case perf_socket_event_connected:
|
||||
stats->num_conn_completed++;
|
||||
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (stats->conn_latency) {
|
||||
hg64_inc(stats->conn_latency, elapsed_time);
|
||||
}
|
||||
#endif
|
||||
stats->conn_latency_sum += elapsed_time;
|
||||
stats->conn_latency_sum_squares += (elapsed_time * elapsed_time);
|
||||
if (elapsed_time < stats->conn_latency_min || stats->num_conn_completed == 1)
|
||||
|
@ -1218,6 +1386,12 @@ threadinfo_init(threadinfo_t* tinfo, const config_t* config,
|
|||
|
||||
perf_list_init(tinfo->outstanding_queries);
|
||||
perf_list_init(tinfo->unused_queries);
|
||||
#ifdef USE_HISTOGRAMS
|
||||
if (config->latency_histogram) {
|
||||
tinfo->stats.latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
tinfo->stats.conn_latency = hg64_create(HISTOGRAM_SIGBITS);
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < NQIDS; i++) {
|
||||
perf_link_init(&tinfo->queries[i]);
|
||||
perf_list_append(tinfo->unused_queries, &tinfo->queries[i]);
|
||||
|
@ -1240,11 +1414,15 @@ threadinfo_init(threadinfo_t* tinfo, const config_t* config,
|
|||
/*
|
||||
* We can't have more than 64k outstanding queries per thread.
|
||||
*/
|
||||
if (tinfo->max_outstanding > NQIDS)
|
||||
if (tinfo->max_outstanding > NQIDS) {
|
||||
perf_log_warning("requested number of outstanding queries (-q %u) per single thread (-T) exceeds built-in maximum %u, adjusting\n", tinfo->max_outstanding, NQIDS);
|
||||
tinfo->max_outstanding = NQIDS;
|
||||
}
|
||||
|
||||
if (tinfo->nsocks > MAX_SOCKETS)
|
||||
if (tinfo->nsocks > MAX_SOCKETS) {
|
||||
perf_log_warning("requested number of clients (-c %u) per thread (-T) exceeds built-in maximum %u, adjusting\n", tinfo->nsocks, MAX_SOCKETS);
|
||||
tinfo->nsocks = MAX_SOCKETS;
|
||||
}
|
||||
|
||||
if (!(tinfo->socks = calloc(tinfo->nsocks, sizeof(*tinfo->socks)))) {
|
||||
perf_log_fatal("out of memory");
|
||||
|
@ -1383,7 +1561,7 @@ int main(int argc, char** argv)
|
|||
print_final_status(&config);
|
||||
|
||||
sum_stats(&config, &total_stats);
|
||||
print_statistics(&config, ×, &total_stats);
|
||||
print_statistics(&config, ×, &total_stats, 0, 0);
|
||||
perf_net_stats_print(config.mode);
|
||||
|
||||
cleanup(&config);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
327
src/ext/hg64.c
Normal file
327
src/ext/hg64.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* hg64 - 64-bit histograms
|
||||
*
|
||||
* Written by Tony Finch <dot@dotat.at> <fanf@isc.org>
|
||||
*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hg64.h"
|
||||
|
||||
/* number of bins is same as number of bits in a value */
|
||||
#define BINS 64
|
||||
|
||||
typedef atomic_uint_fast64_t counter;
|
||||
typedef _Atomic(counter*) bin_ptr;
|
||||
|
||||
struct hg64 {
|
||||
unsigned sigbits;
|
||||
bin_ptr bin[BINS];
|
||||
};
|
||||
|
||||
static inline counter*
|
||||
get_bin(hg64* hg, unsigned b)
|
||||
{
|
||||
/* key_to_new_counter() below has the matching store / release */
|
||||
return (atomic_load_explicit(&hg->bin[b], memory_order_acquire));
|
||||
}
|
||||
|
||||
/*
|
||||
* when we only care about the histogram precision
|
||||
*/
|
||||
struct hg64p {
|
||||
unsigned sigbits;
|
||||
};
|
||||
|
||||
#ifdef __has_attribute
|
||||
#if __has_attribute(__transparent_union__)
|
||||
#define TRANSPARENT __attribute__((__transparent_union__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TRANSPARENT
|
||||
|
||||
typedef union hg64u {
|
||||
hg64* hg;
|
||||
const struct hg64p* hp;
|
||||
} hg64u TRANSPARENT;
|
||||
|
||||
#define hg64p(hu) ((hu).hp)
|
||||
#else
|
||||
|
||||
typedef void* hg64u;
|
||||
|
||||
#define hg64p(hu) ((const struct hg64p*)(hu))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The bins arrays have a static size for simplicity, but that means We
|
||||
* waste a little extra space that could be saved by omitting the
|
||||
* exponents that land in the denormal number bin. The following macros
|
||||
* calculate (at run time) the exact number of keys when we need to do
|
||||
* accurate bounds checks.
|
||||
*/
|
||||
#define DENORMALS(hp) ((hp)->sigbits - 1)
|
||||
#define EXPONENTS(hp) (BINS - DENORMALS(hp))
|
||||
#define MANTISSAS(hp) (1 << (hp)->sigbits)
|
||||
#define KEYS(hp) (EXPONENTS(hp) * MANTISSAS(hp))
|
||||
|
||||
#define BINSIZE(hp) MANTISSAS(hp)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#define OUTARG(ptr, val) (void)(((ptr) != NULL) && (bool)(*(ptr) = (val)))
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
hg64* hg64_create(unsigned sigbits)
|
||||
{
|
||||
if (sigbits < 1 || 15 < sigbits) {
|
||||
return (NULL);
|
||||
}
|
||||
hg64* hg = malloc(sizeof(*hg));
|
||||
hg->sigbits = sigbits;
|
||||
/*
|
||||
* it is probably portable to zero-initialize atomics but the
|
||||
* C standard says we shouldn't rely on it; but this loop
|
||||
* should optimize to memset() on most target systems
|
||||
*/
|
||||
for (unsigned b = 0; b < BINS; b++) {
|
||||
atomic_init(&hg->bin[b], NULL);
|
||||
}
|
||||
return (hg);
|
||||
}
|
||||
|
||||
void hg64_destroy(hg64* hg)
|
||||
{
|
||||
for (unsigned b = 0; b < BINS; b++) {
|
||||
free(get_bin(hg, b));
|
||||
}
|
||||
*hg = (hg64) { 0 };
|
||||
free(hg);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static inline uint64_t
|
||||
key_to_minval(hg64u hu, unsigned key)
|
||||
{
|
||||
unsigned binsize = BINSIZE(hg64p(hu));
|
||||
unsigned exponent = (key / binsize) - 1;
|
||||
uint64_t mantissa = (key % binsize) + binsize;
|
||||
return (key < binsize ? key : mantissa << exponent);
|
||||
}
|
||||
|
||||
/*
|
||||
* don't shift by 64, and don't underflow exponent; instead,
|
||||
* reduce shift by 1 for each hazard and pre-shift UINT64_MAX
|
||||
*/
|
||||
static inline uint64_t
|
||||
key_to_maxval(hg64u hu, unsigned key)
|
||||
{
|
||||
unsigned binsize = BINSIZE(hg64p(hu));
|
||||
unsigned shift = 63 - (key / binsize);
|
||||
uint64_t range = UINT64_MAX / 4 >> shift;
|
||||
return (key_to_minval(hu, key) + range);
|
||||
}
|
||||
|
||||
/*
|
||||
* This branchless conversion is due to Paul Khuong: see bin_down_of() in
|
||||
* https://pvk.ca/Blog/2015/06/27/linear-log-bucketing-fast-versatile-simple/
|
||||
*/
|
||||
static inline unsigned
|
||||
value_to_key(hg64u hu, uint64_t value)
|
||||
{
|
||||
/* fast path */
|
||||
const struct hg64p* hp = hg64p(hu);
|
||||
/* ensure that denormal numbers are all in the same bin */
|
||||
uint64_t binned = value | BINSIZE(hp);
|
||||
int clz = __builtin_clzll((unsigned long long)(binned));
|
||||
/* actually 1 less than the exponent except for denormals */
|
||||
unsigned exponent = 63 - hp->sigbits - clz;
|
||||
/* mantissa has leading bit set except for denormals */
|
||||
unsigned mantissa = value >> exponent;
|
||||
/* leading bit of mantissa adds one to exponent */
|
||||
return ((exponent << hp->sigbits) + mantissa);
|
||||
}
|
||||
|
||||
static counter*
|
||||
key_to_new_counter(hg64* hg, unsigned key)
|
||||
{
|
||||
/* slow path */
|
||||
unsigned binsize = BINSIZE(hg);
|
||||
unsigned b = key / binsize;
|
||||
unsigned c = key % binsize;
|
||||
counter* old_bp = NULL;
|
||||
counter* new_bp = malloc(sizeof(counter) * binsize);
|
||||
/* see comment in hg64_create() above */
|
||||
for (unsigned i = 0; i < binsize; i++) {
|
||||
atomic_init(new_bp + i, 0);
|
||||
}
|
||||
bin_ptr* bpp = &hg->bin[b];
|
||||
if (atomic_compare_exchange_strong_explicit(bpp, &old_bp, new_bp,
|
||||
memory_order_acq_rel, memory_order_acquire)) {
|
||||
return (new_bp + c);
|
||||
} else {
|
||||
/* lost the race, so use the winner's counters */
|
||||
free(new_bp);
|
||||
return (old_bp + c);
|
||||
}
|
||||
}
|
||||
|
||||
static inline counter*
|
||||
key_to_counter(hg64* hg, unsigned key)
|
||||
{
|
||||
/* fast path */
|
||||
unsigned binsize = BINSIZE(hg);
|
||||
unsigned b = key / binsize;
|
||||
unsigned c = key % binsize;
|
||||
counter* bp = get_bin(hg, b);
|
||||
return (bp == NULL ? NULL : bp + c);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
get_key_count(hg64* hg, unsigned key)
|
||||
{
|
||||
counter* ctr = key_to_counter(hg, key);
|
||||
return (ctr == NULL ? 0 : atomic_load_explicit(ctr, memory_order_relaxed));
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_key_count(hg64* hg, unsigned key, uint64_t inc)
|
||||
{
|
||||
if (inc == 0)
|
||||
return;
|
||||
counter* ctr = key_to_counter(hg, key);
|
||||
ctr = ctr ? ctr : key_to_new_counter(hg, key);
|
||||
atomic_fetch_add_explicit(ctr, inc, memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
void hg64_inc(hg64* hg, uint64_t value)
|
||||
{
|
||||
add_key_count(hg, value_to_key(hg, value), 1);
|
||||
}
|
||||
|
||||
bool hg64_get(hg64* hg, unsigned key,
|
||||
uint64_t* pmin, uint64_t* pmax, uint64_t* pcount)
|
||||
{
|
||||
if (key < KEYS(hg)) {
|
||||
OUTARG(pmin, key_to_minval(hg, key));
|
||||
OUTARG(pmax, key_to_maxval(hg, key));
|
||||
OUTARG(pcount, get_key_count(hg, key));
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
hg64_next(hg64* hg, unsigned key)
|
||||
{
|
||||
key++;
|
||||
while (key < KEYS(hg) && (key & (BINSIZE(hg) - 1)) == 0 && key_to_counter(hg, key) == NULL) {
|
||||
key += BINSIZE(hg);
|
||||
}
|
||||
return (key);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://fanf2.user.srcf.net/hermes/doc/antiforgery/stats.pdf
|
||||
*/
|
||||
void hg64_mean_variance(hg64* hg, double* pmean, double* pvar)
|
||||
{
|
||||
double pop = 0.0;
|
||||
double mean = 0.0;
|
||||
double sigma = 0.0;
|
||||
uint64_t min, max, count;
|
||||
for (unsigned key = 0;
|
||||
hg64_get(hg, key, &min, &max, &count);
|
||||
key = hg64_next(hg, key)) {
|
||||
double delta = (double)min / 2.0 + (double)max / 2.0 - mean;
|
||||
if (count != 0) { /* avoid division by zero */
|
||||
pop += count;
|
||||
mean += count * delta / pop;
|
||||
sigma += count * delta * (min + max - mean);
|
||||
}
|
||||
}
|
||||
OUTARG(pmean, mean);
|
||||
OUTARG(pvar, sigma / pop);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
void hg64_merge(hg64* target, hg64* source)
|
||||
{
|
||||
uint64_t count;
|
||||
for (unsigned skey = 0;
|
||||
hg64_get(source, skey, NULL, NULL, &count);
|
||||
skey = hg64_next(source, skey)) {
|
||||
uint64_t svmin = key_to_minval(source, skey);
|
||||
uint64_t svmax = key_to_maxval(source, skey);
|
||||
unsigned tkmin = value_to_key(target, svmin);
|
||||
unsigned tkmax = value_to_key(target, svmax);
|
||||
unsigned keys = tkmax - tkmin + 1;
|
||||
/* is there a more cunning way to spread out the remainder? */
|
||||
uint64_t div = count / keys;
|
||||
uint64_t rem = count % keys;
|
||||
for (unsigned tkey = tkmin; tkey <= tkmax; tkey++) {
|
||||
uint64_t inc = div + (uint64_t)(tkey < rem);
|
||||
add_key_count(target, tkey, inc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hg64_diff(hg64* a, hg64* b, hg64* diff)
|
||||
{
|
||||
assert((a->sigbits == b->sigbits) && (b->sigbits == diff->sigbits));
|
||||
uint64_t count_a = 0;
|
||||
uint64_t count_b = 0;
|
||||
for (unsigned key = 0;
|
||||
hg64_get(a, key, NULL, NULL, &count_a);
|
||||
key++) {
|
||||
hg64_get(b, key, NULL, NULL, &count_b);
|
||||
add_key_count(diff, key, count_a - count_b);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned hg64_min_key(hg64* hg)
|
||||
{
|
||||
uint64_t pcount;
|
||||
for (unsigned key = 0;
|
||||
hg64_get(hg, key, NULL, NULL, &pcount);
|
||||
key = hg64_next(hg, key)) {
|
||||
if (pcount > 0)
|
||||
return key;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned hg64_max_key(hg64* hg)
|
||||
{
|
||||
unsigned last_key = 0;
|
||||
uint64_t pcount;
|
||||
for (unsigned key = 0;
|
||||
hg64_get(hg, key, NULL, NULL, &pcount);
|
||||
key = hg64_next(hg, key)) {
|
||||
if (pcount > 0)
|
||||
last_key = key;
|
||||
}
|
||||
return last_key;
|
||||
}
|
88
src/ext/hg64.h
Normal file
88
src/ext/hg64.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* hg64 - 64-bit histograms
|
||||
*
|
||||
* Written by Tony Finch <dot@dotat.at> <fanf@isc.org>
|
||||
*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef HG64_H
|
||||
#define HG64_H 1
|
||||
|
||||
typedef struct hg64 hg64;
|
||||
|
||||
/*
|
||||
* Allocate a new histogram. `sigbits` must be between 1 and 15
|
||||
* inclusive; it is the number of significant bits of each value
|
||||
* to use when mapping values to buckets.
|
||||
*/
|
||||
hg64* hg64_create(unsigned sigbits);
|
||||
|
||||
/*
|
||||
* Free the memory used by a histogram
|
||||
*/
|
||||
void hg64_destroy(hg64* hg);
|
||||
|
||||
/*
|
||||
* Add 1 to the value's bucket
|
||||
*/
|
||||
void hg64_inc(hg64* hg, uint64_t value);
|
||||
|
||||
/*
|
||||
* Get information about a bucket. This can be used as an iterator,
|
||||
* by initializing `key` to zero and incrementing by one or using
|
||||
* `hg64_next()` until `hg64_get()` returns `false`. The number of
|
||||
* iterations is a little less than `1 << (6 + sigbits)`.
|
||||
*
|
||||
* If `pmin` is non-NULL it is set to the bucket's minimum inclusive value.
|
||||
*
|
||||
* If `pmax` is non-NULL it is set to the bucket's maximum inclusive value.
|
||||
*
|
||||
* If `pcount` is non-NULL it is set to the bucket's counter, which
|
||||
* can be zero. (Empty buckets are included in the iterator.)
|
||||
*/
|
||||
bool hg64_get(hg64* hg, unsigned key,
|
||||
uint64_t* pmin, uint64_t* pmax, uint64_t* pcount);
|
||||
|
||||
/*
|
||||
* Skip to the next key, omitting groups of nonexistent buckets.
|
||||
*/
|
||||
unsigned hg64_next(hg64* hg, unsigned key);
|
||||
|
||||
/*
|
||||
* Get summary statistics about the histogram.
|
||||
*
|
||||
* If `pmean` is non-NULL it is set to the mean of the recorded data.
|
||||
*
|
||||
* If `pvar` is non-NULL it is set to the variance of the recorded
|
||||
* data. The standard deviation is the square root of the variance.
|
||||
*/
|
||||
void hg64_mean_variance(hg64* hg, double* pmean, double* pvar);
|
||||
|
||||
/*
|
||||
* Increase the counts in `target` by the counts recorded in `source`
|
||||
*/
|
||||
void hg64_merge(hg64* target, hg64* source);
|
||||
|
||||
/*
|
||||
* diff = a - b
|
||||
*/
|
||||
void hg64_diff(hg64* a, hg64* b, hg64* diff);
|
||||
|
||||
/*
|
||||
* Get highest key with non-zero value. Returns 0 if all values are 0.
|
||||
*/
|
||||
unsigned hg64_max_key(hg64* hg);
|
||||
|
||||
/*
|
||||
* Get lowest key with non-zero value. Returns 0 if all values are 0.
|
||||
*/
|
||||
unsigned hg64_min_key(hg64* hg);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include "net.h"
|
||||
#include "edns.h"
|
||||
#include "parse_uri.h"
|
||||
#include "ext/parse_uri.h"
|
||||
#include "log.h"
|
||||
#include "strerror.h"
|
||||
#include "util.h"
|
||||
|
@ -324,6 +324,8 @@ static ssize_t perf__doh_recv(struct perf_net_socket* sock, void* buf, size_t le
|
|||
return -1;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
// treat this as a retry, can happen if sendto is reconnecting
|
||||
case ECONNREFUSED:
|
||||
case ECONNRESET:
|
||||
case ENOTCONN:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -177,6 +177,8 @@ static ssize_t perf__dot_recv(struct perf_net_socket* sock, void* buf, size_t le
|
|||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
// treat this as a retry, can happen if sendto is reconnecting
|
||||
case ECONNREFUSED:
|
||||
case ECONNRESET:
|
||||
case ENOTCONN:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -171,6 +171,8 @@ static ssize_t perf__tcp_recv(struct perf_net_socket* sock, void* buf, size_t le
|
|||
return 0;
|
||||
} else if (n < 0) {
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
// treat this as a retry, can happen if sendto is reconnecting
|
||||
case ECONNREFUSED:
|
||||
case ECONNRESET:
|
||||
case ENOTCONN:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
40
src/opt.c
40
src/opt.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -238,39 +238,57 @@ static int perf_opt_long_parse(char* optarg)
|
|||
ssize_t optlen;
|
||||
char* arg;
|
||||
|
||||
// TODO: Allow boolean not to have =/value
|
||||
if (!(arg = strchr(optarg, '='))) {
|
||||
return -1;
|
||||
if ((arg = strchr(optarg, '='))) {
|
||||
arg++;
|
||||
optlen = arg - optarg;
|
||||
if (optlen < 1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
optlen = strlen(optarg);
|
||||
}
|
||||
optlen = arg - optarg;
|
||||
if (optlen < 1) {
|
||||
return -1;
|
||||
}
|
||||
arg++;
|
||||
|
||||
long_opt_t* opt = longopts;
|
||||
while (opt) {
|
||||
if (!strncmp(optarg, opt->name, optlen)) {
|
||||
switch (opt->type) {
|
||||
case perf_opt_string:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.stringp = arg;
|
||||
break;
|
||||
case perf_opt_boolean:
|
||||
*opt->u.boolp = true;
|
||||
break;
|
||||
case perf_opt_uint:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.uintp = parse_uint(opt->desc, arg, 1, 0xFFFFFFFF);
|
||||
break;
|
||||
case perf_opt_zpint:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.uintp = parse_uint(opt->desc, arg, 0, 0xFFFFFFFF);
|
||||
break;
|
||||
case perf_opt_timeval:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.uint64p = parse_timeval(opt->desc, arg);
|
||||
break;
|
||||
case perf_opt_double:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.doublep = parse_double(opt->desc, arg);
|
||||
break;
|
||||
case perf_opt_port:
|
||||
if (!arg) {
|
||||
return -1;
|
||||
}
|
||||
*opt->u.portp = parse_uint(opt->desc, arg, 0, 0xFFFF);
|
||||
break;
|
||||
}
|
||||
|
@ -284,10 +302,10 @@ static int perf_opt_long_parse(char* optarg)
|
|||
|
||||
void perf_long_opt_usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s ... -O <name>=<value> ...\n\nAvailable long options:\n", progname);
|
||||
fprintf(stderr, "Usage: %s ... -O <name>[=<value>] ...\n\nAvailable long options:\n", progname);
|
||||
long_opt_t* opt = longopts;
|
||||
while (opt) {
|
||||
fprintf(stderr, " %s: %s", opt->name, opt->help);
|
||||
fprintf(stderr, " %s%s: %s", opt->name, opt->type != perf_opt_boolean ? "=<val>" : "", opt->help);
|
||||
if (opt->defval) {
|
||||
fprintf(stderr, " (default: %s)", opt->defval);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
2
src/os.c
2
src/os.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
2
src/os.h
2
src/os.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright 2019-2022 OARC, Inc.
|
||||
# Copyright 2019-2023 OARC, Inc.
|
||||
# Copyright 2017-2018 Akamai Technologies
|
||||
# Copyright 2006-2016 Nominum, Inc.
|
||||
# All rights reserved.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Copyright 2019-2022 OARC, Inc.
|
||||
.\" Copyright 2019-2023 OARC, Inc.
|
||||
.\" Copyright 2017-2018 Akamai Technologies
|
||||
.\" Copyright 2006-2016 Nominum, Inc.
|
||||
.\" All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -2,3 +2,8 @@
|
|||
|
||||
../dnsperf -h
|
||||
../resperf -h
|
||||
|
||||
! ../dnsperf -O suppress
|
||||
! ../dnsperf -O suppress=
|
||||
! ../resperf -O suppress
|
||||
! ../resperf -O suppress=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019-2022 OARC, Inc.
|
||||
* Copyright 2019-2023 OARC, Inc.
|
||||
* Copyright 2017-2018 Akamai Technologies
|
||||
* Copyright 2006-2016 Nominum, Inc.
|
||||
* All rights reserved.
|
||||
|
|
Loading…
Add table
Reference in a new issue