mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
chg: dev: Add option to compile named with static linking and LTO
Statically linking lib{isc,dns,ns,cfg,isccc} and enabling LTO shows over 10% improvements on all almost measurements in perflab. That said, we can't use Meson's option for LTO since it would result in every binary being compiled with LTO and a great increase in compile time.
To work around it, we add a configuration option that enables LTO and static linking only for the `named` binary.
Merge branch 'alessio/meson-lto-v2' into 'main'
See merge request isc-projects/bind9!10761
This commit is contained in:
commit
b6971fb724
16 changed files with 211 additions and 58 deletions
|
|
@ -1214,7 +1214,7 @@ scan-build:
|
|||
variables:
|
||||
CC: "${CLANG}"
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
EXTRA_CONFIGURE: "-Didn=enabled"
|
||||
EXTRA_CONFIGURE: "-Didn=enabled --native-file ci/clang-trixie.ini"
|
||||
before_script:
|
||||
- *list_installed_package_versions
|
||||
script:
|
||||
|
|
@ -1427,7 +1427,7 @@ clang:asan:
|
|||
variables:
|
||||
CC: ${CLANG}
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
EXTRA_CONFIGURE: "-Db_sanitize=address,undefined -Db_lundef=false -Didn=enabled -Djemalloc=disabled -Dtracing=disabled"
|
||||
EXTRA_CONFIGURE: "-Db_sanitize=address,undefined -Db_lundef=false -Didn=enabled -Djemalloc=disabled -Dtracing=disabled --native-file ci/clang-trixie.ini"
|
||||
<<: *base_image
|
||||
<<: *build_job
|
||||
|
||||
|
|
@ -1487,7 +1487,8 @@ clang:tsan:
|
|||
CC: "${CLANG}"
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
LDFLAGS: "-Wl,--disable-new-dtags"
|
||||
EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false"
|
||||
EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false -Dnamed-lto=off --native-file ci/clang-trixie.ini"
|
||||
<<: *build_job
|
||||
|
||||
system:clang:tsan:
|
||||
variables:
|
||||
|
|
@ -1542,6 +1543,7 @@ clang:trixie:amd64:
|
|||
variables:
|
||||
CC: ${CLANG}
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
EXTRA_CONFIGURE: "--native-file ci/clang-trixie.ini"
|
||||
RUN_MESON_INSTALL: 1
|
||||
<<: *debian_trixie_amd64_image
|
||||
<<: *build_job
|
||||
|
|
@ -1801,7 +1803,7 @@ respdiff:tsan:
|
|||
CC: "${CLANG}"
|
||||
CFLAGS: "${CFLAGS_COMMON}"
|
||||
LDFLAGS: "-Wl,--disable-new-dtags"
|
||||
EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false"
|
||||
EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Dnamed-lto=off -Db_lundef=false"
|
||||
MAX_DISAGREEMENTS_PERCENTAGE: "0.3"
|
||||
TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}"
|
||||
script:
|
||||
|
|
@ -1928,9 +1930,13 @@ reproducible-build:
|
|||
before_script:
|
||||
- *list_installed_package_versions
|
||||
script:
|
||||
# dnstap produces an intermediate .a file, and meson considers all .a
|
||||
# files to be final results independently of whether they are installed or
|
||||
# not. But the content of the .a file might be unstable under LTO due to
|
||||
# -ffat-lto-objects. Hence we disable dnstap for reproducibility tests.
|
||||
- meson reprotest
|
||||
--intermediaries
|
||||
--
|
||||
-Ddnstap=disabled
|
||||
-Ddoc=disabled
|
||||
-Doptimization=1
|
||||
artifacts:
|
||||
|
|
|
|||
20
ci/clang-trixie.ini
Normal file
20
ci/clang-trixie.ini
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# 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/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# LTO builds with clang
|
||||
|
||||
[binaries]
|
||||
ar = 'llvm-ar-20'
|
||||
c = 'clang-20'
|
||||
c_ld = 'lld'
|
||||
|
||||
[project options]
|
||||
named-lto = 'thin'
|
||||
|
|
@ -87,6 +87,22 @@ To improve performance, use of the ``jemalloc`` library
|
|||
(https://jemalloc.net/) is strongly recommended. Version 4.0.0 or newer is
|
||||
required when in use.
|
||||
|
||||
To further improve performance, compilation with link-time optimization is
|
||||
recommended. This is enabled by default via the ``-Dnamed-lto`` option
|
||||
(default: ``thin``). Link-time optimization can be disabled if needed by
|
||||
using ``-Dnamed-lto=off``. The optimization level can be controlled with
|
||||
``-Dnamed-lto=thin`` or ``-Dnamed-lto=full``.
|
||||
|
||||
Link-time optimization requires close coordination between the compiler and
|
||||
the linker. Due to ``clang`` limitations, compiling ``named`` with ``clang``
|
||||
and link-time optimization is only supported with the ``lld`` linker.
|
||||
|
||||
Meson provides an alternative way to enable link-time optimization through
|
||||
the ``-Db_lto=true`` flag. However, this option is incompatible with
|
||||
BIND's ``-Dnamed-lto`` option. Meson's ``-Db_lto`` may also be incompatible
|
||||
with certain BIND build options and can result in lower performance and
|
||||
higher compile times compared to ``-Dnamed-lto``.
|
||||
|
||||
To support :rfc:`DNS over HTTPS (DoH) <8484>`, the server must be linked
|
||||
with ``libnghttp2`` (https://nghttp2.org/). If the library is
|
||||
unavailable, ``-Ddoh=disabled`` can be used to disable DoH support.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
probe_src = [dtrace_header.process('probes.d'), files('xfrin.c')]
|
||||
probe_hdr = dtrace_header.process('probes-dns.d')
|
||||
probe_src = [probe_hdr, files('xfrin.c')]
|
||||
|
||||
# dns_inc += include_directories('include')
|
||||
dns_inc_p += include_directories('.')
|
||||
|
|
@ -57,17 +58,20 @@ endif
|
|||
|
||||
dns_srcset.add(
|
||||
when: 'HAVE_DTRACE',
|
||||
if_true: custom_target(
|
||||
'dns-probe',
|
||||
input: [files('probes.d'), dns_probe_objects],
|
||||
output: 'dns-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
if_true: [
|
||||
custom_target(
|
||||
'dns-probe',
|
||||
input: [files('probes-dns.d'), dns_probe_objects],
|
||||
output: 'dns-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
probe_hdr,
|
||||
],
|
||||
if_false: probe_src,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#include "probes.h"
|
||||
#include "probes-dns.h"
|
||||
|
||||
/*
|
||||
* Incoming AXFR and IXFR.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "job_p.h"
|
||||
#include "loop_p.h"
|
||||
#include "probes.h"
|
||||
#include "probes-isc.h"
|
||||
|
||||
/*
|
||||
* Public: #include <isc/job.h>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
|
||||
probe_src = []
|
||||
|
||||
probe_src += [dtrace_header.process('probes.d'), files('job.c')]
|
||||
probe_hdr = dtrace_header.process('probes-isc.d')
|
||||
probe_src += [probe_hdr, files('job.c')]
|
||||
if config.get('USE_PTHREAD_RWLOCK') != 1
|
||||
probe_src += files('rwlock.c')
|
||||
endif
|
||||
|
|
@ -47,17 +48,20 @@ endif
|
|||
|
||||
isc_srcset.add(
|
||||
when: 'HAVE_DTRACE',
|
||||
if_true: custom_target(
|
||||
'isc-probe',
|
||||
input: [files('probes.d'), isc_probe_objects],
|
||||
output: 'isc-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
if_true: [
|
||||
custom_target(
|
||||
'isc-probe',
|
||||
input: [files('probes-isc.d'), isc_probe_objects],
|
||||
output: 'isc-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
probe_hdr,
|
||||
],
|
||||
if_false: probe_src,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@
|
|||
#include <isc/uv.h>
|
||||
|
||||
#include "../loop_p.h"
|
||||
#include "../openssl_shim.h"
|
||||
#include "netmgr-int.h"
|
||||
#include "openssl_shim.h"
|
||||
|
||||
isc__netmgr_t *isc__netmgr = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
#include <isc/tid.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "probes.h"
|
||||
#include "probes-isc.h"
|
||||
|
||||
static atomic_uint_fast16_t isc__crwlock_workers = 128;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
probe_src = [dtrace_header.process('probes.d'), files('query.c')]
|
||||
probe_hdr = dtrace_header.process('probes-ns.d')
|
||||
probe_src = [probe_hdr, files('query.c')]
|
||||
|
||||
if config.get('HAVE_DTRACE')
|
||||
ns_probe_objects += static_library(
|
||||
|
|
@ -25,17 +26,20 @@ endif
|
|||
|
||||
ns_srcset.add(
|
||||
when: 'HAVE_DTRACE',
|
||||
if_true: custom_target(
|
||||
'ns-probe',
|
||||
input: [files('probes.d'), ns_probe_objects],
|
||||
output: 'ns-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
if_true: [
|
||||
custom_target(
|
||||
'ns-probe',
|
||||
input: [files('probes-ns.d'), ns_probe_objects],
|
||||
output: 'ns-probes.o',
|
||||
command: [
|
||||
dtrace,
|
||||
'-G',
|
||||
'-o', '@OUTPUT@',
|
||||
'-s', '@INPUT@',
|
||||
],
|
||||
),
|
||||
probe_hdr,
|
||||
],
|
||||
if_false: probe_src,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
#include <ns/stats.h>
|
||||
#include <ns/xfrout.h>
|
||||
|
||||
#include "probes.h"
|
||||
#include "probes-ns.h"
|
||||
|
||||
#if 0
|
||||
/*
|
||||
|
|
|
|||
115
meson.build
115
meson.build
|
|
@ -45,6 +45,7 @@ developer_mode = get_option('developer').enabled()
|
|||
c_std = get_option('c_std')
|
||||
optimization = get_option('optimization')
|
||||
sanitizer = get_option('b_sanitize')
|
||||
meson_lto = get_option('b_lto')
|
||||
|
||||
trace_logging = get_option('trace-logging')
|
||||
rcu_flavor = get_option('rcu-flavor')
|
||||
|
|
@ -64,6 +65,7 @@ leak_opt = get_option('leak-detection')
|
|||
line_opt = get_option('line')
|
||||
lmdb_opt = get_option('lmdb')
|
||||
locktype_opt = get_option('locktype')
|
||||
named_lto_opt = get_option('named-lto')
|
||||
stats_json_opt = get_option('stats-json')
|
||||
stats_xml_opt = get_option('stats-xml')
|
||||
tracing_opt = get_option('tracing')
|
||||
|
|
@ -898,6 +900,61 @@ assert(
|
|||
'tracing is requested but dtrace is not found',
|
||||
)
|
||||
|
||||
# LTO
|
||||
|
||||
static_lto_c_args = []
|
||||
static_lto_link_args = []
|
||||
|
||||
if named_lto_opt == 'full'
|
||||
static_lto_c_args = ['-ffat-lto-objects', '-flto']
|
||||
static_lto_link_args = ['-flto']
|
||||
elif named_lto_opt == 'thin' and cc.get_id() == 'clang' and cc.get_linker_id() == 'ld.lld'
|
||||
# Per LLVM docs [1], -ffat-lto-objects is supported only with lld and gold,
|
||||
# and gold is deprecated/unmantained.
|
||||
# [1]: https://llvm.org/docs/FatLTO.html
|
||||
|
||||
static_lto_c_args = ['-ffat-lto-objects', '-flto=thin']
|
||||
static_lto_link_args = ['-flto=thin']
|
||||
elif named_lto_opt == 'thin' and cc.get_id() == 'gcc'
|
||||
static_lto_c_args = ['-ffat-lto-objects', '-flto=auto']
|
||||
static_lto_link_args = ['-flto=auto']
|
||||
elif named_lto_opt == 'thin'
|
||||
error('LTO requires clang with ld.lld, or gcc with any linker')
|
||||
endif
|
||||
|
||||
add_project_arguments(static_lto_c_args, language: 'c')
|
||||
if named_lto_opt != 'off' and cc.get_id() == 'clang' and sanitizer.contains('address')
|
||||
# Needed to suppress the
|
||||
# warning: Redundant instrumentation detected, with module flag:
|
||||
# nosanitize_address [-Werror,-Wbackend-plugin]
|
||||
# warning in address sanitizer. This warning indicates that the object file
|
||||
# has been processed already by address sanitizer instrumentation pass.
|
||||
# From looking at the pass code, when address sanitizer detects that
|
||||
# an object file has already been instrumented, it just skips it.
|
||||
# Therefore it should be safe to suppress the warning.
|
||||
|
||||
add_project_arguments('-Wno-backend-plugin', language: 'c')
|
||||
endif
|
||||
|
||||
if meson_lto and named_lto_opt != 'off'
|
||||
# Meson's builtin LTO settings do not set -ffat-lto-objects, which can cause
|
||||
# build issues.
|
||||
# Since we don't want two, possibly conflicting, sets of LTO flags, we
|
||||
# error out if both are set.
|
||||
|
||||
error(
|
||||
'''
|
||||
Meson builtin -Db_lto and BIND's -Dnamed-lto options are incompatible.
|
||||
Either disable named-lto with -Dnamed-lto=off, or avoid setting
|
||||
-Db_lto.
|
||||
|
||||
Note that using -Db_lto is not a recommended configuration, might
|
||||
yield reduced performance compared to -Dnamed-lto and conflict
|
||||
with other build flags.
|
||||
''',
|
||||
)
|
||||
endif
|
||||
|
||||
### Finalize configuration
|
||||
configure_file(output: 'config.h', configuration: config)
|
||||
add_project_arguments('-include', meson.project_build_root() / 'config.h', language: 'c')
|
||||
|
|
@ -1158,8 +1215,6 @@ libisccfg_dep = declare_dependency(
|
|||
include_directories: isccfg_inc,
|
||||
)
|
||||
|
||||
named_srcconf = named_srcset.apply(config, strict: false)
|
||||
|
||||
executable(
|
||||
'arpaname',
|
||||
arpaname_src,
|
||||
|
|
@ -1459,22 +1514,58 @@ executable(
|
|||
|
||||
)
|
||||
|
||||
executable(
|
||||
'named',
|
||||
named_srcconf.sources(),
|
||||
export_dynamic: true,
|
||||
implicit_include_directories: true,
|
||||
include_directories: named_inc_p,
|
||||
install: true,
|
||||
install_dir: sbindir,
|
||||
sources: bind_keys,
|
||||
dependencies: [
|
||||
named_c_args = []
|
||||
named_link_args = []
|
||||
named_deps = []
|
||||
|
||||
if named_lto_opt == 'off'
|
||||
named_deps = [
|
||||
libdns_dep,
|
||||
libisc_dep,
|
||||
libisccc_dep,
|
||||
libisccfg_dep,
|
||||
libns_dep,
|
||||
]
|
||||
named_inc = named_inc_p
|
||||
|
||||
named_objects = []
|
||||
else
|
||||
named_deps = [
|
||||
dns_srcconf.dependencies(),
|
||||
isc_srcconf.dependencies(),
|
||||
isccc_srcconf.dependencies(),
|
||||
isccfg_srcconf.dependencies(),
|
||||
ns_srcconf.dependencies(),
|
||||
]
|
||||
named_inc = [isc_inc, dns_inc, isccc_inc, isccfg_inc, ns_inc, named_inc_p]
|
||||
|
||||
named_srcset.add(dns_gen_headers)
|
||||
|
||||
named_objects = [
|
||||
libisc.extract_all_objects(recursive: true),
|
||||
libdns.extract_all_objects(recursive: true),
|
||||
libns.extract_all_objects(recursive: true),
|
||||
libisccc.extract_all_objects(recursive: true),
|
||||
libisccfg.extract_all_objects(recursive: true),
|
||||
]
|
||||
endif
|
||||
|
||||
named_srcconf = named_srcset.apply(config, strict: false)
|
||||
|
||||
executable(
|
||||
'named',
|
||||
named_srcconf.sources(),
|
||||
objects: named_objects,
|
||||
c_args: static_lto_c_args,
|
||||
link_args: static_lto_link_args,
|
||||
export_dynamic: true,
|
||||
implicit_include_directories: true,
|
||||
include_directories: named_inc,
|
||||
install: true,
|
||||
install_dir: sbindir,
|
||||
sources: bind_keys,
|
||||
dependencies: named_deps
|
||||
+ [
|
||||
openssl_dep,
|
||||
|
||||
cap_dep,
|
||||
|
|
|
|||
|
|
@ -188,3 +188,11 @@ option(
|
|||
value: 'disabled',
|
||||
description: 'enable the memory leak detection in external libraries (libxml2, libuv, OpenSSL)',
|
||||
)
|
||||
|
||||
option(
|
||||
'named-lto',
|
||||
type: 'combo',
|
||||
choices: ['off', 'thin', 'full'],
|
||||
value: 'thin',
|
||||
description: 'Enable Link Time Optimization for named.',
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue