Skip to content

feat: NPU metrics logger daemon#14

Open
Sam Freund (samfreund-qc) wants to merge 5 commits into
qualcomm:mainfrom
samfreund-qc:npu-logger
Open

feat: NPU metrics logger daemon#14
Sam Freund (samfreund-qc) wants to merge 5 commits into
qualcomm:mainfrom
samfreund-qc:npu-logger

Conversation

@samfreund-qc

Copy link
Copy Markdown

Summary

Adds QcPerfNpuLogger, a standalone systemd-compatible daemon that uses the public qcperf_* API to continuously sample all four NPU metrics and write a point-in-time snapshot to /var/log/qcperf/npu_metrics.log once per second.

What it does

The daemon connects to QC_PERF_BACKEND_DSP_NPU, samples at 100 ms intervals, and fires a streaming callback every 1000 ms. Each callback atomically replaces the output file (write to .npu_metrics.tmp, then rename(2)) so readers never observe a partial write. The most recent sample per metric within each streaming window is kept; earlier samples are discarded.

Output format:

Q6 Utilization:42.50
Q6 Clock:614400.00
HVX Utilization:12.30
HMX Utilization:8.70

Files added

File Purpose
qcperf/npu_logger/src/qcperf_npu_logger.c Daemon implementation (main, callbacks, helpers)
qcperf/npu_logger/systemd/qcperf-npu-logger.service systemd unit with hardened sandbox
qcperf/npu_logger/CMakeLists.txt Build rules, opt-in via -DBUILD_NPU_LOGGER=ON

Build

cmake -S qcperf -B build-linux-aarch64-release \
    -DTARGET_ARCH=linux-aarch64 \
    -DCMAKE_BUILD_TYPE=Release \
    -DProjectVersion="0.1.0.0" \
    -DBACKENDS="CPU;NPU;DUMMY" \
    -DBUILD_NPU_LOGGER=ON
cmake --build build-linux-aarch64-release

The target is off by default. Enabling it without NPU in BACKENDS emits a CMake warning and skips the build gracefully.

Runtime requirement

/usr/lib/libcdsprpc.so must be present on the target device. If absent, the dynamic linker fails at process startup — this is a constraint of the underlying FastRPC transport, not something the daemon can work around.

systemd unit highlights

  • ProtectSystem=strict + LogsDirectory=qcperf (creates /var/log/qcperf before the namespace is set up, required for first install)
  • PrivateTmp=true, NoNewPrivileges=true
  • Restart=on-failure with a 5 s back-off
  • Logs to the systemd journal via SyslogIdentifier=qcperf-npu-logger

Testing

Run on a Qualcomm Linux ARM64 device with libcdsprpc.so present:

# Start the daemon manually
/usr/bin/QcPerfNpuLogger &

# Verify output
cat /var/log/qcperf/npu_metrics.log

# Or via systemd
systemctl enable --now qcperf-npu-logger
journalctl -u qcperf-npu-logger -f

Checklist

  • BSD 3-Clause copyright header present
  • Single exit point per function
  • All variables declared at top of function (C89 style)
  • No goto, no always-true loops
  • Yoda-style null checks (NULL == ptr)
  • calloc used instead of malloc; pointers set to NULL after free
  • snake_case / PascalCase / UPPER_CASE naming conventions followed
  • Doxygen comments on all functions
  • clang-format — not available on the development host; please run before merge: clang-format -i qcperf/npu_logger/src/qcperf_npu_logger.c

Signed-off-by: samfreund-qc <freund@qti.qualcomm.com>
ProtectSystem=strict sets up a mount namespace before ExecStartPre runs.
That namespace setup requires ReadWritePaths to already exist, causing a
226/NAMESPACE failure on first install when /var/log/qcperf doesn't exist.

Replace ExecStartPre=/bin/mkdir + ReadWritePaths= with LogsDirectory=qcperf.
systemd creates LogsDirectory-managed paths before namespace setup.

Signed-off-by: samfreund-qc <freund@qti.qualcomm.com>
Signed-off-by: samfreund-qc <freund@qti.qualcomm.com>
Signed-off-by: samfreund-qc <freund@qti.qualcomm.com>
- Move uint8_t cleanup declaration to top of copy_backend_info() to
  comply with C89-style variable declarations at function scope.
- Rewrite main loop as while (0 != g_running) to avoid the always-true
  loop pattern prohibited by the Semgrep rules.

Signed-off-by: samfreund-qc <freund@qti.qualcomm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant