Skip to content

feat: benchmark stability improvements (CPU pinning, swap control, image pinning)#7

Merged
kamilchodola merged 5 commits intomainfrom
feat/benchmark-stability-improvements
Feb 27, 2026
Merged

feat: benchmark stability improvements (CPU pinning, swap control, image pinning)#7
kamilchodola merged 5 commits intomainfrom
feat/benchmark-stability-improvements

Conversation

@kamilchodola
Copy link
Contributor

@kamilchodola kamilchodola commented Feb 27, 2026

Summary

  • CPU pinning (cpuset / infra_cpuset): Optional Docker --cpuset-cpus support to pin execution client and infrastructure containers to specific CPU cores. Useful on shared machines to isolate benchmark workloads. On dedicated machines, leaving these unset (letting the scheduler spread threads across all physical cores) typically gives better throughput.
  • Memory swappiness (mem_swappiness): Optional Docker --memory-swappiness control for the execution client container. Defaults to host setting (not passed to Docker) to avoid page cache eviction in I/O-heavy workloads.
  • Preflight checks: Warns at startup about suboptimal system configuration:
    • CPU governor not set to performance
    • Transparent Huge Pages enabled (always mode)
    • Noisy systemd timers that can cause I/O/CPU spikes (sysstat, apt-daily, fwupd, fstrim)
    • All warnings include copy-paste fix commands in the log message
  • Pinned Docker image versions: Default K6 (1.6.1) and Alloy (v1.13.2) images pinned to specific versions instead of :latest for reproducible benchmarks. Can be overridden in config.
  • Updated example config: HT-aware cpuset examples with topology documentation

Important notes

  • All new config fields (cpuset, infra_cpuset, mem_swappiness) are optional with safe defaults. Existing configs work without changes.
  • CPU pinning tradeoff: Pinning to N logical CPUs on fewer physical cores reduces throughput vs letting the scheduler use all physical cores. Only pin when you need isolation from other workloads. Ensure pinned logical CPUs map to distinct physical cores (lscpu -e=CPU,CORE,SOCKET).
  • mem_swappiness should generally be left unset. Setting it to 0 aggressively evicts page cache, which devastates I/O-heavy workloads like Ethereum execution clients.

Test plan

  • Run with no cpuset/infra_cpuset/mem_swappiness set — should match main branch performance
  • Run with cpuset/infra_cpuset set — verify containers are pinned via docker inspect
  • Verify preflight warnings appear when governor is not performance, THP is always, or noisy timers are active
  • Verify no warnings on a properly configured system
  • Verify existing configs without new fields still parse correctly

… for benchmark stability

Add cpuset/infra_cpuset fields to pin execution client and infrastructure
containers to dedicated CPU cores, eliminating scheduler migration noise.
Add mem_swappiness control (default 0) to prevent swap-induced latency spikes.
Pin K6 and Alloy Docker images to specific versions for reproducible runs.
Add CPU governor preflight warning when not set to 'performance'.
mem_swappiness=0 aggressively evicts page cache to protect anonymous
memory, which devastates I/O-heavy workloads like Nethermind that rely
on page cache for state DB reads. Defaulting to None (host setting)
preserves the previous behavior and avoids unexpected slowdowns.
Don't pass None values to Docker SDK containers.run() — some SDK
versions may convert None to 0 for integer fields like mem_swappiness,
silently changing container behavior. Build kwargs conditionally instead.
- Expand CPU governor check into broader preflight checks that also warn
  about Transparent Huge Pages (always mode) and active systemd timers
  known to cause I/O/CPU spikes during benchmarks
- Update example cpuset values to show HT-aware pinning that avoids
  sharing physical cores between execution client and infra containers
Move the fix commands from structured log kwargs into the warning
message text so they are always visible in log output.
@kamilchodola kamilchodola merged commit 56f83b1 into main Feb 27, 2026
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