Skip to content
Closed
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
5 changes: 4 additions & 1 deletion src/modules/mavlink/mavlink_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,10 @@ Mavlink::forward_message(const mavlink_message_t *msg, Mavlink *self)
return;
}

LockGuard lg{mavlink_module_mutex};
// No mutex needed: instances can't be destroyed while receiver threads run
// (destroy_all_instances() stops all threads first). Pointer reads are
// naturally atomic on aligned architectures. pass_message() has its own
// per-instance _message_buffer_mutex for the ring buffer.

for (Mavlink *inst : mavlink_module_instances) {
if (inst && (inst != self) && (inst->get_forwarding_on())) {
Expand Down
26 changes: 26 additions & 0 deletions test/mavsdk_tests/CMakeLists_bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.5.1)

project(mavlink_forwarding_bench CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

find_package(MAVSDK REQUIRED)
find_package(Threads REQUIRED)

add_executable(mavlink_forwarding_bench
test_mavlink_forwarding_bench.cpp
)

target_link_libraries(mavlink_forwarding_bench
MAVSDK::mavsdk
${CMAKE_THREAD_LIBS_INIT}
)

target_compile_options(mavlink_forwarding_bench
PRIVATE
-Wall
-Wextra
-Werror
)
117 changes: 117 additions & 0 deletions test/mavsdk_tests/run_forwarding_bench.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/bin/bash
#
# MAVLink forwarding mutex benchmark runner.
#
# Builds the benchmark tool, starts PX4 SITL SIH, runs the benchmark,
# then collects perf counter data.
#
# Usage:
# ./run_forwarding_bench.sh [--duration 60] [--rate 200] [--connections 2] [--label baseline]
#
# The --label flag tags the output files for before/after comparison.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PX4_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
BUILD_DIR="$SCRIPT_DIR/build_bench"
RESULTS_DIR="$PX4_DIR/bench_results"

DURATION=60
RATE=200
CONNECTIONS=2
LABEL="run"

while [[ $# -gt 0 ]]; do
case "$1" in
--duration) DURATION="$2"; shift 2 ;;
--rate) RATE="$2"; shift 2 ;;
--connections) CONNECTIONS="$2"; shift 2 ;;
--label) LABEL="$2"; shift 2 ;;
--help|-h)
echo "Usage: $0 [--duration N] [--rate N] [--connections N] [--label NAME]"
exit 0
;;
*) echo "Unknown arg: $1"; exit 1 ;;
esac
done

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RESULT_PREFIX="${RESULTS_DIR}/${LABEL}_${TIMESTAMP}"

mkdir -p "$RESULTS_DIR"

echo "=== Step 1: Build PX4 SITL SIH ==="
cd "$PX4_DIR"
make px4_sitl_sih 2>&1 | tail -5

echo ""
echo "=== Step 2: Build benchmark tool ==="
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Symlink the standalone CMakeLists and source into build dir
ln -sf "$SCRIPT_DIR/CMakeLists_bench.txt" CMakeLists.txt
ln -sf "$SCRIPT_DIR/test_mavlink_forwarding_bench.cpp" .
cmake -DCMAKE_BUILD_TYPE=Release .
make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)

echo ""
echo "=== Step 3: Start PX4 SITL SIH ==="
cd "$PX4_DIR"

# Start PX4 in background, capture PID
PX4_SIM_MODEL=sihsim_quadx $PX4_DIR/build/px4_sitl_sih/bin/px4 \
-s $PX4_DIR/ROMFS/px4fmu_common/init.d-posix/rcS \
-w $PX4_DIR/build/px4_sitl_sih/rootfs \
$PX4_DIR/build/px4_sitl_sih/etc \
> "${RESULT_PREFIX}_px4.log" 2>&1 &
PX4_PID=$!

echo "PX4 started (PID=$PX4_PID), waiting 10s for boot..."
sleep 10

# Verify PX4 is running
if ! kill -0 "$PX4_PID" 2>/dev/null; then
echo "ERROR: PX4 failed to start. Check ${RESULT_PREFIX}_px4.log"
exit 1
fi

echo ""
echo "=== Step 4: Run benchmark ==="
echo " Duration: ${DURATION}s"
echo " Rate: ${RATE} Hz/connection"
echo " Connections: ${CONNECTIONS}"
echo ""

"$BUILD_DIR/mavlink_forwarding_bench" \
--duration "$DURATION" \
--rate "$RATE" \
--connections "$CONNECTIONS" \
--report "${RESULT_PREFIX}_sender.csv" \
2>&1 | tee "${RESULT_PREFIX}_bench.log"

echo ""
echo "=== Step 5: Perf counters ==="
echo "The benchmark tool reads perf counters from the board automatically"
echo "via the MAVLink shell protocol. Check the bench log above for BENCH lines."

echo ""
echo "=== Step 6: Stop PX4 ==="
kill -INT "$PX4_PID" 2>/dev/null || true
Comment on lines +93 to +100
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The script claims to “collect perf counter data” and has a “Step 5: Collect perf counters”, but it never actually issues the perf command to the PX4 console/MAVLink shell. As written, ${RESULT_PREFIX}_perf.txt will usually be missing unless PX4 happens to dump perf counters on exit.

Either implement the perf collection step (e.g. via mavlink shell/pxh) or update the step text and header comment so expectations match what the script really does.

Copilot uses AI. Check for mistakes.
wait "$PX4_PID" 2>/dev/null || true

# Extract bench lines from the benchmark log if available
if grep -q "BENCH" "${RESULT_PREFIX}_bench.log" 2>/dev/null; then
echo "Perf counters:"
grep "BENCH" "${RESULT_PREFIX}_bench.log" | tee "${RESULT_PREFIX}_perf.txt"
fi

echo ""
echo "=== Results saved ==="
echo " PX4 log: ${RESULT_PREFIX}_px4.log"
echo " Bench log: ${RESULT_PREFIX}_bench.log"
echo " Sender CSV: ${RESULT_PREFIX}_sender.csv"
echo " Perf data: ${RESULT_PREFIX}_perf.txt (if available)"
echo ""
echo "To compare runs:"
echo " diff <baseline>_perf.txt <after_fix>_perf.txt"
Loading
Loading