Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AFLplusplus/AFLplusplus/llms.txt
Use this file to discover all available pages before exploring further.
The afl-gotcpu utility provides an accurate measurement of CPU availability and preemption rates to help determine the optimal number of parallel fuzzing instances.
Synopsis
Description
afl-gotcpu measures CPU preemption rates on each core to determine how many AFL++ instances you can effectively run. It accounts for system load and other processes that may be competing for CPU time.
This tool is particularly useful for:
- Determining optimal fuzzer parallelization
- Identifying overloaded or idle cores
- Planning fuzzing infrastructure
- Avoiding CPU contention
Usage
# Run without arguments
afl-gotcpu
The tool has no command-line options.
Example Output
afl-gotcpu++4.10c by Michal Zalewski
Measuring per-core preemption rate (this will take 2.00 sec)...
+----------------------+
| Core | Util | Status |
+------+------+--------+
| 0 | 12% | IDLE |
| 1 | 89% | MAYBE |
| 2 | 5% | IDLE |
| 3 | 8% | IDLE |
| 4 | 45% | MAYBE |
| 5 | 95% | BUSY |
| 6 | 3% | IDLE |
| 7 | 7% | IDLE |
+----------------------+
>>> SYSTEM SUMMARY <<<
Cores available: 8
Cores idle: 5
Cores maybe: 2
Cores busy: 1
Recommended for CPU-bound fuzzing: 5-7 instances
Max with some I/O wait: 7-8 instances
Interpreting Results
Core Status
Core is mostly unused (<20% utilized). Safe to run a fuzzer here.
- Preemption rate: <20%
- Recommendation: Run fuzzer on this core
Core has moderate load (20-80% utilized). May work for fuzzing but could have contention.
- Preemption rate: 20-80%
- Recommendation: Use if needed, monitor performance
Core is heavily loaded (>80% utilized). Avoid running fuzzers here.
- Preemption rate: >80%
- Recommendation: Don’t use for fuzzing
Examples
Basic Usage
# Check CPU availability
afl-gotcpu
# Results show 6 idle cores
# Start 6 fuzzing instances
afl-fuzz -M fuzzer01 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer02 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer03 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer04 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer05 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer06 -i seeds -o sync -- ./target @@ &
Optimal Parallel Setup
# 1. Check availability
afl-gotcpu
# Shows: 5-7 instances recommended
# 2. Start with recommended number
for i in {1..6}; do
if [ $i -eq 1 ]; then
afl-fuzz -M fuzzer$(printf %02d $i) -i seeds -o sync -- ./target @@ &
else
afl-fuzz -S fuzzer$(printf %02d $i) -i seeds -o sync -- ./target @@ &
fi
done
# 3. Monitor performance
watch -n 60 'afl-whatsup -s sync'
I/O-Bound Targets
# If target does I/O (network, disk), you can run more instances
afl-gotcpu
# Shows: Max with I/O wait: 8 instances
# Can run 8+ instances because they'll spend time waiting
for i in {1..8}; do
# Assign to specific core
afl-fuzz -S fuzzer$i -b $((i-1)) -i seeds -o sync -- ./target @@ &
done
Dedicated Fuzzing Machine
# On a dedicated fuzzing server
afl-gotcpu
# Shows: all cores idle
# Use N-1 cores (leave one for system)
NUM_CORES=$(nproc)
NUM_FUZZERS=$((NUM_CORES - 1))
for i in $(seq 1 $NUM_FUZZERS); do
if [ $i -eq 1 ]; then
afl-fuzz -M main -i seeds -o sync -- ./target @@ &
else
afl-fuzz -S fuzzer$i -i seeds -o sync -- ./target @@ &
fi
done
Use Cases
Pre-Fuzzing Setup
# Before starting a fuzzing campaign
# 1. Configure system
sudo afl-system-config
# 2. Check CPU availability
afl-gotcpu
# 3. Start appropriate number of fuzzers
# (based on afl-gotcpu recommendations)
Dynamic Scaling
#!/bin/bash
# auto_scale_fuzzers.sh
# Check current CPU availability
IDLE=$(afl-gotcpu | grep "Cores idle:" | awk '{print $3}')
# Count running fuzzers
RUNNING=$(pgrep -c afl-fuzz)
# Start more if cores are available
if [ $IDLE -gt 2 ] && [ $RUNNING -lt 8 ]; then
echo "Starting additional fuzzer..."
NEXT=$((RUNNING + 1))
afl-fuzz -S fuzzer$NEXT -i - -o sync -- ./target @@ &
fi
Shared Server Setup
# On a shared development server
afl-gotcpu
# Shows: 2 idle cores, 6 busy
# Only use the 2 idle cores
afl-fuzz -M fuzzer01 -b 2 -i seeds -o sync -- ./target @@ &
afl-fuzz -S fuzzer02 -b 5 -i seeds -o sync -- ./target @@ &
Technical Details
Measurement Method
The tool:
- Binds to each CPU core individually
- Runs a tight CPU-bound loop for ~2 seconds
- Measures actual CPU time vs. wall clock time
- Calculates preemption rate from the difference
// Simplified algorithm
start_time = get_wall_clock_time();
start_cpu = get_cpu_time();
// Run busy loop for target duration
while (get_wall_clock_time() - start_time < 2000ms) {
// Busy work
}
end_time = get_wall_clock_time();
end_cpu = get_cpu_time();
// Calculate preemption
wall_delta = end_time - start_time;
cpu_delta = end_cpu - start_cpu;
preemption_rate = (wall_delta - cpu_delta) / wall_delta;
Why It Matters
Running too many fuzzers:
- Causes context switching overhead
- Reduces individual fuzzer performance
- May not increase overall throughput
- Can slow down the whole system
Running too few fuzzers:
- Wastes available CPU resources
- Reduces diversity in fuzzing strategies
- Misses parallelization benefits
Recommendations
CPU-Bound Fuzzing
# For pure CPU-bound targets (no I/O)
# Use: number of idle cores
afl-gotcpu # Shows 6 idle cores
# Run exactly 6 instances
I/O-Bound Fuzzing
# For targets with I/O (network, disk, sleep)
# Use: 1.5x to 2x number of cores
afl-gotcpu # Shows 8 cores
# Can run 12-16 instances
Mixed Workload
# On a system running other tasks
# Use: only truly idle cores
afl-gotcpu # Shows 3 idle, 2 maybe, 3 busy
# Run 3-5 instances maximum
Comparison with Load Average
# Load average (traditional)
uptime
# load average: 2.45, 2.12, 1.98
# vs. afl-gotcpu (precise per-core measurement)
afl-gotcpu
# Core 0: IDLE, Core 1: BUSY, Core 2: IDLE, ...
# afl-gotcpu is more accurate for fuzzing planning
Automation
Launch Script
#!/bin/bash
# smart_launch.sh - Auto-detect optimal fuzzer count
TMPFILE=$(mktemp)
afl-gotcpu > "$TMPFILE"
IDLE=$(grep "Cores idle:" "$TMPFILE" | awk '{print $3}')
MAYBE=$(grep "Cores maybe:" "$TMPFILE" | awk '{print $3}')
NUM_FUZZERS=$((IDLE + MAYBE / 2))
echo "Starting $NUM_FUZZERS fuzzing instances..."
for i in $(seq 1 $NUM_FUZZERS); do
if [ $i -eq 1 ]; then
afl-fuzz -M main -i seeds -o sync -- ./target @@ &
else
afl-fuzz -S fuzzer$i -i seeds -o sync -- ./target @@ &
fi
sleep 1
done
rm "$TMPFILE"
echo "Launched $NUM_FUZZERS fuzzers"
Supported on:
- Linux
- FreeBSD
- NetBSD
- macOS (x86_64 only, limited on ARM)
- DragonFly BSD
- Solaris
Note: ARM64 macOS has limited support due to CPU core architecture differences.
Tips
Before Starting Campaign
# 1. Configure system
sudo afl-system-config
# 2. Check CPU
afl-gotcpu
# 3. Stop unnecessary services
sudo systemctl stop unnecessary-service
# 4. Re-check
afl-gotcpu # Should show more idle cores
# 5. Start fuzzing
Regular Monitoring
# Check periodically during fuzzing
watch -n 300 afl-gotcpu # Every 5 minutes
# Adjust fuzzer count if cores become busy/idle
Cloud Instances
# On cloud VMs, check if you're getting full cores
afl-gotcpu
# Some cloud providers oversell CPUs
# If cores show as BUSY on idle instance, consider:
# - Different instance type
# - Dedicated instances
# - Bare metal
See Also