Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions scripts/docker/build/ubuntu24/Dockerfile.cb
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,15 @@ RUN git clone --depth 1 --no-single-branch ${source}

#
# Install build dependencies for all branches from v4 onwards
# Debian sid fails if debian/control doesn't exist due to an issue
# in one of the included make files, so we create a blank file.
#
WORKDIR freeradius-server
RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[4-9]*\.[0-9x]*\.x|master|${branch})$" | sort -u); \
do \
git checkout $i; \
if [ -e ./debian/control.in ] ; then \
touch -t 202001010000 debian/control; \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the number?

debian/rules debian/control ; \
fi ; \
mk-build-deps -irt"apt-get -o Debug::pkgProblemResolver=yes $APT_OPTS" debian/control ; \
Expand Down
116 changes: 116 additions & 0 deletions scripts/docker/build/ubuntu24/Dockerfile.prof
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Auto generated for ubuntu24
# from scripts/docker/m4/profiling.deb.m4
#
# Rebuild this file with `make profiling.ubuntu24.regen`
#
ARG from=freeradius40x-build/ubuntu24
FROM ${from}

# Copy profiling profile scripts into the container
COPY scripts/docker/profiling/profiles/default-profiling /profile

#
# Install profiling tools
#
# Valgrind/cachegrind
# kcachegrind + KDE/Qt libs
# gperftools
# heaptrack
#
RUN apt-get update && \
apt-get install -y $APT_OPTS \
libgoogle-perftools-dev \
google-perftools \
valgrind \
heaptrack \
psmisc \
kcachegrind \
kio \
libkf5iconthemes5 \
libkf5parts5 \
libkf5textwidgets5 \
libqt5gui5 \
libqt5widgets5 && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

#
# Set up Ubuntu debug symbol repository and install OS library debug symbols.
# These allow profiling tools to resolve system library calls.
#
RUN apt-get update && \
apt-get install -y $APT_OPTS ubuntu-dbgsym-keyring && \
printf 'deb http://ddebs.ubuntu.com noble main restricted universe multiverse\ndeb http://ddebs.ubuntu.com noble-updates main restricted universe multiverse\n' \
> /etc/apt/sources.list.d/ddebs.list && \
apt-get update && \
apt-get install -y $APT_OPTS \
libc6-dbg \
zlib1g-dbgsym \
libreadline8t64-dbgsym \
libssl3t64-dbgsym \
libsasl2-2-dbgsym \
libpam0g-dbgsym \
libldap2-dbgsym \
libtalloc2-dbgsym \
libpcre2-8-0-dbgsym \
libpcap0.8t64-dbgsym \
libunbound8-dbgsym \
libsqlite3-0-dbgsym \
libpq5-dbgsym \
libmariadb3-dbgsym \
libgdbm6t64-dbgsym \
libjson-c5-dbgsym \
libbrotli1-dbgsym \
libhiredis1.1.0-dbgsym \
librdkafka1-dbgsym \
libwbclient0-dbgsym && \
(apt-get install -y $APT_OPTS libcurl4t64-dbgsym || true) && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

ENV DEBUGINFOD_URLS="https://debuginfod.ubuntu.com"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?


#
# Rebuild libkqueue from source with debug symbols.
# CMAKE_BUILD_TYPE must be explicitly set to prevent
# the libkqueue project from overriding the flags.
# libkqueue source currently uses "-O2 -g -DNDEBUG" by default.
#
RUN apt-get update && \
apt-get install -y $APT_OPTS --no-install-recommends cmake git && \
apt-get clean && \
rm -r /var/lib/apt/lists/* && \
git clone --depth 1 https://github.com/mheily/libkqueue.git /tmp/libkqueue && \
cd /tmp/libkqueue && \
cmake -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_FLAGS_RELWITHDEBINFO="-g3 -O1 -fno-omit-frame-pointer -DNDEBUG" \
. && \
make && \
cpack -G DEB && \
dpkg -i *.deb && \
cd / && rm -rf /tmp/libkqueue

#
# Install FlameGraph
#
RUN git clone --depth 1 https://github.com/brendangregg/FlameGraph /opt/flamegraph \
&& chmod +x /opt/flamegraph/*.pl /opt/flamegraph/*.sh

# Add FlameGraph to path
ENV PATH="/opt/flamegraph:${PATH}"

#
# Install Inferno for callgrind. Inferno is a Rust port of FlameGraph with broader format support
#
RUN apt-get update && \
apt-get install -y $APT_OPTS --no-install-recommends \
cargo && \
cargo install inferno --version 0.11.21 --locked --root /usr/local && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

EXPOSE 1812/udp 1813/udp
CMD ["/bin/sh", "-c", "while true; do sleep 60; done"]
51 changes: 51 additions & 0 deletions scripts/docker/crossbuild.mk
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ endif
CB_IPREFIX:=freeradius40x-build
CB_CPREFIX:=fr40x-crossbuild-

PROFILE ?= default-profiling

# Where profiling profiles live
PROFILES_DIR:=$(CB_DIR)/profiling/profiles

# All available profiling profiles (one sub-directory per profile)
CB_PROFILES:=$(sort $(patsubst $(PROFILES_DIR)/%,%,$(wildcard $(PROFILES_DIR)/*)))

#
# This Makefile is included in-line, and not via the "boilermake"
# wrapper. But it's still useful to use the same process for
Expand Down Expand Up @@ -90,6 +98,12 @@ crossbuild.help: crossbuild.info
@echo " crossbuild.IMAGE.clean - stop container and tidy up"
@echo " crossbuild.IMAGE.wipe - remove Docker image"
@echo ""
@echo "Profiling targets:"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely convinced these should be in the help. They should be used by the CI jobs only, it's not helpful to have extra targets for developers that they should never use.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a minor point, help is useful. :) Especially if I want to run profiling tools locally.

As seen here, it's a bit of a pain to get the profiling builds up and running. It's a lot easier to do make profiling

So I'm OK with leaving this in.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on the ones that developers use. But some of these targets are really only for CI, which might be confusing if a developer tries to use them. They're the ones I suggest not adding to help :)

As long as it's clear, then np.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the targets are only for CI, then there's no need to print them out in the help text.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda like having those in the help text :) Helps my brain, but I'm okay to remove the extra info in the help text is that's what we prefer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the targets are useful for developers, especially when used with profiling multi-server tests.

@echo " crossbuild.IMAGE.profile.regen - regenerate Dockerfile.prof using default profile ($(PROFILE))"
@echo " crossbuild.IMAGE.profile.regen PROFILE=<name> - regenerate using a specific profile"
@echo " crossbuild.IMAGE.profile.build - build profiling image using default profile ($(PROFILE))"
@echo " crossbuild.IMAGE.profile.reset - remove profiling stamp to force rebuild"
@echo ""
@echo "Use 'make NOCACHE=1 ...' to disregard the Docker cache on build"

#
Expand Down Expand Up @@ -140,6 +154,20 @@ $(DD)/stamp-image.${1}:
${Q}docker build $(DOCKER_BUILD_OPTS) $(DT)/${1} -f $(DT)/${1}/Dockerfile.cb -t $(CB_IPREFIX)/${1} >$(DD)/build.${1} 2>&1
${Q}touch $(DD)/stamp-image.${1}

#
# Build the profiling image
#
.PHONY: crossbuild.${1}.profile.build
crossbuild.${1}.profile.build: $(DD)/stamp-image.${1}-profile.build

$(DD)/stamp-image.${1}-profile.build: $(DT)/${1}/Dockerfile.prof
${Q}echo "BUILD ${1} (freeradius4-$(PROFILE)/${1}) > $(DD)/build.${1}-profile.build"
${Q}docker build $(DOCKER_BUILD_OPTS) . \
-f $(DT)/${1}/Dockerfile.prof \
-t freeradius4-$(PROFILE)/${1} \
>$(DD)/build.${1}-profile.build 2>&1
${Q}touch $(DD)/stamp-image.${1}-profile.build

#
# Start up the docker container
#
Expand Down Expand Up @@ -249,6 +277,29 @@ $(DT)/${1}/Dockerfile.cb: $(DOCKER_TMPL) $(CB_DIR)/m4/crossbuild.deb.m4 $(CB_DIR
${Q}echo REGEN ${1}
${Q}m4 -I $(CB_DIR)/m4 -D D_NAME=${1} -D D_TYPE=crossbuild $$< > $$@

#
# Regenerate Dockerfile.prof from m4 template
#
.PHONY: crossbuild.${1}.profile.regen
crossbuild.${1}.profile.regen: $(DT)/${1}/Dockerfile.prof

$(DT)/${1}/Dockerfile.prof: $(DOCKER_TMPL) $(CB_DIR)/m4/profiling.deb.m4
${Q}echo REGEN ${1}
${Q}m4 -I $(CB_DIR)/m4 \
-D D_NAME=${1} \
-D D_TYPE=profiling \
-D CB_IMAGE=$(CB_IPREFIX)/${1} \
-D PROFILE_NAME=$(PROFILE) \
$$< > $$@

#
# Remove profiling stamp so next profile.build starts clean
#
.PHONY: crossbuild.${1}.profile.reset
crossbuild.${1}.profile.reset:
${Q}echo RESET profiling ${1}
${Q}rm -f $(DD)/stamp-image.${1}-profile.build

#
# Run the build test
#
Expand Down
111 changes: 111 additions & 0 deletions scripts/docker/m4/profiling.deb.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
ARG from=CB_IMAGE
FROM ${from}

# Copy profiling profile scripts into the container
COPY scripts/docker/profiling/profiles/PROFILE_NAME /profile

#
# Install profiling tools
#
# Valgrind/cachegrind
# kcachegrind + KDE/Qt libs
# gperftools
# heaptrack
#
RUN apt-get update && \
apt-get install -y $APT_OPTS \
libgoogle-perftools-dev \
google-perftools \
valgrind \
heaptrack \
psmisc \
kcachegrind \
kio \
libkf5iconthemes5 \
libkf5parts5 \
libkf5textwidgets5 \
libqt5gui5 \
libqt5widgets5 && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

#
# Set up Ubuntu debug symbol repository and install OS library debug symbols.
# These allow profiling tools to resolve system library calls.
#
RUN apt-get update && \
apt-get install -y $APT_OPTS ubuntu-dbgsym-keyring && \
printf 'deb http://ddebs.ubuntu.com OS_CODENAME main restricted universe multiverse\ndeb http://ddebs.ubuntu.com OS_CODENAME-updates main restricted universe multiverse\n' \
> /etc/apt/sources.list.d/ddebs.list && \
apt-get update && \
apt-get install -y $APT_OPTS \
libc6-dbg \
zlib1g-dbgsym \
libreadline8t64-dbgsym \
libssl3t64-dbgsym \
libsasl2-2-dbgsym \
libpam0g-dbgsym \
libldap2-dbgsym \
libtalloc2-dbgsym \
libpcre2-8-0-dbgsym \
libpcap0.8t64-dbgsym \
libunbound8-dbgsym \
libsqlite3-0-dbgsym \
libpq5-dbgsym \
libmariadb3-dbgsym \
libgdbm6t64-dbgsym \
libjson-c5-dbgsym \
libbrotli1-dbgsym \
libhiredis1.1.0-dbgsym \
librdkafka1-dbgsym \
libwbclient0-dbgsym && \
(apt-get install -y $APT_OPTS libcurl4t64-dbgsym || true) && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

ENV DEBUGINFOD_URLS="https://debuginfod.ubuntu.com"

#
# Rebuild libkqueue from source with debug symbols.
# CMAKE_BUILD_TYPE must be explicitly set to prevent
# the libkqueue project from overriding the flags.
# libkqueue source currently uses "-O2 -g -DNDEBUG" by default.
#
RUN apt-get update && \
apt-get install -y $APT_OPTS --no-install-recommends cmake git && \
apt-get clean && \
rm -r /var/lib/apt/lists/* && \
git clone --depth 1 https://github.com/mheily/libkqueue.git /tmp/libkqueue && \
cd /tmp/libkqueue && \
cmake -G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_FLAGS_RELWITHDEBINFO="-g3 -O1 -fno-omit-frame-pointer -DNDEBUG" \
. && \
make && \
cpack -G DEB && \
dpkg -i *.deb && \
cd / && rm -rf /tmp/libkqueue

#
# Install FlameGraph
#
RUN git clone --depth 1 https://github.com/brendangregg/FlameGraph /opt/flamegraph \
&& chmod +x /opt/flamegraph/*.pl /opt/flamegraph/*.sh

# Add FlameGraph to path
ENV PATH="/opt/flamegraph:${PATH}"

#
# Install Inferno for callgrind. Inferno is a Rust port of FlameGraph with broader format support
#
RUN apt-get update && \
apt-get install -y $APT_OPTS --no-install-recommends \
cargo && \
cargo install inferno --version 0.11.21 --locked --root /usr/local && \
apt-get clean && \
rm -r /var/lib/apt/lists/*

EXPOSE 1812/udp 1813/udp
CMD ["/bin/sh", "-c", "while true; do sleep 60; done"]
43 changes: 43 additions & 0 deletions scripts/docker/profiling/profiles/default-profiling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Default Profiling Profile

Default profiling profile for FreeRADIUS, using Valgrind. The scripts in this directory are copied into the profiling Docker image at build time.

## Scripts

| Script | Description |
|----------------|----------------------------------------------------------------|
| `configure.sh` | Configures the FreeRADIUS build with profiling options enabled |
| `start.sh` | Starts the profiling session |

## Building the image

The profiling image is built on top of a crossbuild image using the make targets defined in
[scripts/docker/crossbuild.mk](../../../../../crossbuild.mk). The `Dockerfile.prof` is generated
from the m4 template at [scripts/docker/m4/profiling.deb.m4](../../../../m4/profiling.deb.m4).

```sh
# Regenerate Dockerfile.prof (if the m4 template changed)
make crossbuild.IMAGE.profile.regen

# Build the profiling image
make crossbuild.IMAGE.profile.build
```

Replace `IMAGE` with the target OS, e.g. `ubuntu24`. This profile is used by default
(`PROFILE=default-profiling`). To use a different profile:

```sh
make crossbuild.IMAGE.profile.build PROFILE=<name>
```

## Usage

Once inside the container:

```sh
# Configure the FreeRADIUS build
./configure.sh

# Start profiling
./start.sh
```
20 changes: 20 additions & 0 deletions scripts/docker/profiling/profiles/default-profiling/configure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
set -e

# CFLAGS used for profiling build:
# -g3 Maximum debug info for callgrind symbol resolution
# -O1 Basic optimisation for realistic hotspot costs; inlining/vectorisation/
# unrolling disabled below so the call graph matches the source.
# -fno-omit-frame-pointer Keep frame pointers for callgrind stack walking
# -fno-inline Preserve call edges (suppresses CC_HINT(flatten) too)
# -Dalways_inline= Strip always_inline, which -fno-inline does not suppress
# -fno-plt Resolve cross-library calls via GOT rather than PLT stubs;
# PLT stubs have no DWARF info and show as ??? in callgrind.
# -fno-builtin Keep stdlib calls (memcpy, strlen, etc.) visible in the graph
# -fno-optimize-sibling-calls Suppress tail-call elimination (-O1 can still apply it)
./configure \
--enable-developer \
--disable-verify-ptr \
--with-raddbdir=/etc/freeradius \
CFLAGS="-g3 -O1 -fno-omit-frame-pointer -fno-inline -Dalways_inline= -fno-plt -fno-builtin -fno-optimize-sibling-calls" \
LDFLAGS="-fno-omit-frame-pointer"
Loading
Loading