cargo test -- --test-threads=1
cargo test -- --test-threads=1means:
Build and run all Rust tests in the current Cargo package, but execute only one test at a time.
Let’s break it down.
1. cargo test
cargo testCargo finds the tests in your project and runs them.
For example, if your project contains:
ffmpeg_rs/
├── src/
│ ├── lib.rs
│ ├── codec/
│ │ ├── pcm.rs
│ │ ├── h264.rs
│ │ └── ...
│ └── ...
└── tests/
├── decoder.rs
└── encoder.rsthen:
cargo testdoes not mean “test the file I’m currently editing.”
It generally builds the test targets and runs the tests discovered in the package.
2. Why the second --?
The command has:
cargo test -- --test-threads=1
↑The first -- separates Cargo arguments from test-harness arguments.
Think of it as:
cargo test
│
├── arguments before `--`
│ → Cargo
│
└── arguments after `--`
→ Rust test executableSo:
cargo test -- --test-threads=1means:
Cargo:
"Build and run the tests."
Test harness:
"Run with only one test thread."3. --test-threads=1
Normally:
cargo testallows multiple tests to execute concurrently.
For example:
CPU
│
├── test A
├── test B
├── test C
├── test D
└── test EWith:
cargo test -- --test-threads=1you get:
CPU
│
└── test A
↓
finish
↓
test B
↓
finish
↓
test C
↓
finishSo it is useful when debugging tests that interfere with one another or when investigating unexpectedly high CPU usage.
4. In your ffmpeg_rs project
When you ran:
cargo test -- --test-threads=1you were not testing only pcm.rs.
You were telling Cargo to run the test suite for the package, with the test harness restricted to one test at a time.
That’s an important distinction.
If you have:
src/codec/pcm.rs
src/codec/aac.rs
src/codec/h264.rs
src/format/muxer.rs
...and they contain #[test] functions, those tests can all be included.
Your uploaded pcm.rs itself contains many #[test] functions, but cargo test is not limited to that file.
5. How to see exactly what is being tested
Use:
cargo test -- --listThis doesn’t run the tests. It lists them.
You’ll get something similar to:
codec::pcm::tests::decoder_s16le: test
codec::pcm::tests::decoder_s24le: test
codec::pcm::tests::encoder_s16le: test
codec::pcm::tests::round_trip: test
...Then you can run a specific test:
cargo test decoder_s16leor:
cargo test round_trip6. If you specifically want to test pcm.rs
Rust’s normal unit-test model doesn’t work like:
cargo test pcm.rsInstead, you normally filter by the test name/module path.
For example:
cargo test pcmwill run tests whose names match pcm.
You can combine that with single-threaded execution:
cargo test pcm -- --test-threads=1And if you want to see output:
cargo test pcm -- --test-threads=1 --nocaptureSo for your CPU investigation, I’d start with:
cargo test pcm -- --test-threads=1 --nocaptureThen, if that still consumes 100% CPU, we know the problem is much more specifically associated with the PCM tests rather than another test elsewhere in ffmpeg_rs.
test 2
- This output is very useful. We can now narrow the problem down substantially.
1. The process tree is completely normal
You have:
systemd
└─ ghostty
└─ fish
└─ cargo test -- --test-threads=1
└─ ffmpeg_rs-92bbeda044d74837 --test-threads=1
└─ {ffmpeg_rs-92bbe}Specifically:
PID 6540 = cargo
PID 6551 = Rust test executable
PID 6720 = thread inside Rust test executableSo:
cargo
│
└── test executable
│
└── test thread 6720There is no mysterious orphaned process here.
2. The important clue is PID 6720
Your earlier output showed:
6551 6540 99.9% ... ffmpeg_rs-... --test-threads=1And pstree shows:
└─{ffmpeg_rs-92bbe},6720That means the test executable has a thread with PID/TID:
6720This is very likely the thread actually consuming the CPU.
--test-threads=1 means the Rust test harness is configured to execute one test at a time. It does not mean the entire process can only have one OS thread. Libraries/runtime code can still create additional threads.
In your case, however, the process tree only shows one additional thread, so we should inspect it directly.
3. Check CPU per thread
Run:
ps -L -p 6551 -o pid,tid,psr,%cpu,stat,etime,commYou should get something like:
PID TID PSR %CPU STAT ELAPSED COMMAND
6551 6551 3 0.0 Sl 01:30 ffmpeg_rs-92bbe
6551 6720 7 99.9 R 01:30 ffmpeg_rs-92bbeThe interesting part would be:
TID 6720
CPU 99.9%
STAT RR means running.
That would establish:
ffmpeg_rs process
│
└── TID 6720
│
└── 100% CPU4. This is now looking like a CPU-bound loop
The fact that:
ELAPSED = 01:20
CPU = 99.9%is significant.
The process has been alive for ~80 seconds and has accumulated roughly:
CPU time ≈ 80 secondsfor one core.
This is very different from a process simply waiting for I/O.
For example, if it were waiting on a file/socket:
CPU: 0%
state: Swould be more typical.
Instead:
CPU: ~100%suggests the thread is actively executing instructions.
5. Now find the exact function
This is the most important next step.
Run:
sudo perf top -p 6551Let it run for around 5–10 seconds.
You want the top entries.
For example, if you see:
85.0% ffmpeg_rs ffmpeg_rs::codec::pcm::receive_frame
8.0% ffmpeg_rs ffmpeg_rs::codec::pcm::send_packet
2.0% ffmpeg_rs ...then we know the PCM implementation is actually responsible.
But if you see:
90% ffmpeg_rs some_other_functionthen we know the PCM code isn’t the culprit.
6. An even more targeted command
Because this is your debug test executable, try:
sudo perf record -g -p 6551 -- sleep 5Then:
sudo perf reportThe -g records the call graph.
You might get something like:
Children Self Command Shared Object Symbol
--------------------------------------------------------------
99.8% 99.8% ffmpeg_rs ffmpeg_rs pcm::...
99.8% ... ffmpeg_rs ffmpeg_rs test_...The call stack is what we really want.
7. You can also inspect the thread with GDB
Attach to the process:
gdb -p 6551Then:
info threadsYou may see:
Id Target Id Frame
* 1 Thread ... (LWP 6551) ...
2 Thread ... (LWP 6720) ...Switch to the suspicious thread:
thread 2Then:
btOr, even better:
thread apply all btThat should show exactly what Rust is doing.
8. There’s one especially important possibility in your project
Your process is:
ffmpeg_rs-92bbeda044d74837Notice that this is the test binary for the entire crate.
It is not necessarily testing only:
pcm.rsWhen you run:
cargo test -- --test-threads=1Cargo builds the crate’s complete test executable and runs all unit tests in that executable.
So even though you were investigating pcm.rs, the CPU-intensive test could be somewhere else in your FFmpeg Rust port.
The process name:
ffmpeg_rs-92bbeda044d74837doesn’t tell us which test is running.
9. Find the test that is currently running
Run:
cargo test -- --test-threads=1 --nocaptureIf your tests print nothing, add temporary prints around suspicious tests:
#[test]
fn some_test() {
eprintln!("START some_test");
// test code
eprintln!("END some_test");
}Then you’ll see:
START test_a
ok
START test_bIf you get:
START test_band then CPU goes to 100% forever:
START test_b
↓
100% CPU
↓
never returnsyou have identified the test.
10. One thing I would NOT blame now
I would not blame:
--test-threads=1anymore.
That option was a good diagnostic, and your result is actually useful.
You have demonstrated:
Multiple test threads?
│
└── No
CPU still ~100%?
│
└── YesTherefore the problem is likely:
single test
↓
calls some function
↓
function becomes CPU-bound
↓
doesn't terminateor:
single test
↓
calls library code
↓
library creates/uses a worker thread
↓
worker consumes CPU11. I would run these three commands next
A. Identify the CPU-consuming thread
ps -L -p 6551 -o pid,tid,psr,%cpu,stat,etime,commB. Identify the function
sudo perf top -p 6551C. Identify the call stack
sudo gdb -p 6551then:
thread apply all btMy current diagnosis
The evidence now looks like this:
CPU
│
▼
cargo 6540
│
│
▼
ffmpeg_rs test process 6551
│
│
▼
thread/TID 6720
│
│
~100%
│
▼
CPU-bound codeSo we’ve ruled out an orphaned Cargo process and ordinary test parallelism.
The next piece of evidence we need is the symbol/call stack for TID 6720. perf top -p 6551 is the quickest. If you paste that output, I can tell you which part of your FFmpeg Rust code is actually causing the 100% CPU usage.
ps & pstree
- Yes — this output makes the situation much clearer.
The important line
PID PPID %CPU %MEM ELAPSED CMD
6551 6540 99.9 7.2 01:20 .../target/debug/deps/ffmpeg_rs-92bbeda044d74837 --test-threads=1Your Rust test executable itself is consuming essentially one full CPU core:
CPU = 99.9%
Memory = 7.2%
Runtime = 1 minute 20 secondsSo the problem is not Firefox, GNOME, or the terminal. It is definitely this process:
ffmpeg_rs-92bbeda044d74837And because you ran:
--test-threads=1this is not caused by multiple Rust test threads running simultaneously.
1. The process hierarchy is important
You have:
6551 6540 99.9% ffmpeg_rs-... --test-threads=1So PID 6540 is the parent of the test executable.
Run:
ps -fp 6540and:
pstree -aps 6551I expect you’ll see something similar to:
cargo
└── ffmpeg_rs-92bbeda044d74837
└── test threadThe critical question now is:
Why is this particular test binary still running for 1+ minutes?
Your pcm.rs tests should not normally take anywhere near that long.
2. This is probably not normal PCM processing
From the PCM file you uploaded, the actual decoder/encoder operations contain finite loops.
For example, the decoder’s byte-swapping path processes the packet and terminates, and the 24-bit conversion path also iterates over a finite packet size.
Likewise, the encoder has finite loops for byte swapping and 24-bit conversion.
The tests themselves also use bounded collections/loops. For example, the lookup test iterates over a fixed expect collection.
And the round-trip test iterates over a fixed set of cases.
I don’t see an obvious:
loop {
...
}or:
while condition {
// condition never changes
}in this file.
So 99.9% CPU for 80 seconds strongly suggests that the test executable is stuck somewhere else, or one of the tests is exercising code outside the PCM implementation.
3. First: find exactly which test is stuck
Run:
cargo test -- --test-threads=1 --nocaptureThe important difference is:
--nocaptureNormally Rust captures test output.
With:
--nocaptureyou’ll see output from the tests directly.
Even better, list the tests first:
cargo test -- --listYou should get something like:
test_pcm_decode_s16le: test
test_pcm_decode_s24be: test
test_pcm_encode_s16le: test
...Then run individual tests:
cargo test test_pcm_decode_s16le -- --nocaptureIf that finishes immediately:
cargo test test_pcm_decode_s24be -- --nocaptureetc.
This lets us find the exact test that causes the CPU spike.
4. Even better: attach strace
Since you’re on Linux, this is probably the most useful next diagnostic.
First stop the current process:
kill 6551Then run:
strace -f -p 6551But only if PID 6551 is still alive.
If it is already gone, start the test again:
cargo test -- --test-threads=1Find the PID:
pgrep -af ffmpeg_rsThen:
strace -f -p <PID>If it is actually stuck in a userspace CPU loop, you may see very few/no system calls.
For example:
strace: Process 6551 attachedand then essentially nothing.
That would be a strong indication of:
Rust code
↓
tight userspace loop
↓
100% CPU
↓
no syscalls5. perf is even better for this particular problem
Because you’re investigating why Rust code consumes 100% CPU, I’d recommend perf.
Run:
sudo perf top -p 6551You’ll see something similar to:
Samples: ...
Overhead Symbol
80.2% some_function
12.4% another_function
4.1% ...This is extremely valuable.
If you see something like:
ffmpeg_rs::codec::pcm::...then we’ve found the problem.
If instead you see:
std::thread::parkor:
futexthen it’s a synchronization issue.
If you see:
regex
alloc
hashbrown
...then the CPU is being consumed somewhere else.
6. You can also get the backtrace of the running process
Try:
sudo gdb -p 6551Then inside GDB:
thread apply all btThis is particularly useful because it tells us exactly where the thread is executing.
For example:
Thread 1:
#0 pcm_decode(...)
#1 receive_frame(...)
#2 ...
#3 ...Then we know immediately where to investigate.
Exit:
quit7. One interesting clue: 7.2% memory
This part:
%MEM
7.2is somewhat interesting.
Your test process is using significantly more memory than the other processes shown.
However, %MEM is system-wide percentage, not “7.2% of the Rust program’s allocation.”
Get the actual memory size:
ps -p 6551 -o pid,%cpu,%mem,rss,vsz,etime,cmdFor example:
PID %CPU %MEM RSS VSZ ELAPSED CMD
6551 99.9 7.2 123456 456789 00:01:20 ...The important values are:
RSS— actual resident physical memoryVSZ— virtual address space%CPU— CPU consumption
If RSS is continuously increasing, that’s another important clue.
8. Check whether memory is growing
Run:
watch -n 1 'ps -p 6551 -o pid,%cpu,%mem,rss,vsz,etime,cmd'You might see:
PID %CPU %MEM RSS VSZ
6551 99.9 7.2 500000 800000
6551 99.9 7.3 510000 810000
6551 99.9 7.4 520000 820000
6551 99.9 7.5 530000 830000If RSS continuously increases:
500 MB
510 MB
520 MB
530 MB
...then we’re potentially looking at a memory allocation loop / runaway test.
If memory remains stable:
500 MB
500 MB
501 MB
500 MBthen it’s more likely a CPU-bound loop.
9. Important: --test-threads=1 proves something
You originally suspected the Rust test runner might be spawning many tests.
But your new output is:
ffmpeg_rs-... --test-threads=1and:
99.9% CPUTherefore:
cargo test
│
└── test binary
│
└── ONE test thread
│
└── ~100% CPUSo we can eliminate the simple explanation:
“Rust is running dozens of tests simultaneously.”
That’s not what’s happening.
10. The most useful command now
I’d like you to run this while PID 6551 is consuming 100% CPU:
sudo perf top -p 6551Give it about 5–10 seconds, then copy the top ~20 lines here.
Also run:
ps -p 6551 -o pid,ppid,%cpu,%mem,rss,vsz,etime,cmdAnd:
pstree -aps 6551Those three outputs should let us narrow this down considerably.
Current diagnosis
Firefox ~16%
Rust test executable ~100% ← PROBLEM
GNOME Shell ~8%
everything else lowSo we’ve now confirmed that the 100% CPU is coming from the ffmpeg_rs test binary itself, not from the desktop environment.
The next step is to determine which function/test inside that binary is burning the CPU. perf top -p 6551 is probably the fastest way to find it.