Unix app-server: fork/exec becomes CPU-bound after memory growth
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Linux: app-server fork/exec is CPU-heavy with a large address space
What version of the Codex App are you using?
Codex App 26.825.51511
codex-rs 0.152.0-alpha.7.2
What subscription do you have?
Pro
What platform is your computer?
Linux 7.1.8 x86_64 unknown
What issue are you seeing?
After approximately 66 hours, the app-server had grown to:
VmSize: 30.5 GB
VmRSS: 11.6 GB
RssAnon: 11.6 GB
VmSwap: 12.0 GB
It used roughly 20–30% CPU while launching commands.
Of 183 PID-scoped cpu-clock samples, 64.48% were in the Linux clone/execve paths:
39.34% execve
exit_mmap
__zap_vma_range
swap_put_entries_cluster
swap_pte_batch
25.14% clone
copy_process
dup_mmap
copy_page_range
swap_dup_entries_cluster
This is consistent with copying and immediately destroying the large process’s page tables during fork → exec.
Current upstream spawn paths install Unix pre_exec callbacks:
On Linux and macOS, these callbacks force Rust’s fork/exec fallback instead of an otherwise eligible posix_spawn path.
Rust’s Unix process implementation rejects the posix_spawn path when pre_exec closures are present:
|| !self.get_closures().is_empty()
{
return Ok(None);
}
The memory-growth cause is unknown.
After restarting Codex, the new app-server used approximately 488 MiB RSS after 70 seconds.
What steps can reproduce the bug?
I have not isolated a deterministic reproduction.
The issue appeared after running Codex App for several days with multiple tasks and frequent command execution.
Once the app-server had accumulated a large anonymous address space, command launches consistently triggered the page-table paths above.
What is the expected behavior?
Command-launch cost should not grow materially with the long-lived app-server’s memory mappings.
One possible direction is a small, early-started spawn broker for ordinary non-PTY commands.
It could perform the required fork, pre_exec, and exec without copying the app-server’s page tables, while preserving parent-death, file-descriptor, and process-group semantics.
PTY launches can retain their existing path.
Additional information
The profile was captured on Linux.
macOS uses the same pre_exec-dependent spawn path, but I did not measure its runtime behavior
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with codex-rs/core/src/spawn.rs and codex-rs/utils/pty/src/pipe.rs, focusing on the Unix pre_exec callbacks and the ordinary versus PTY launch paths. Review the linked Rust Unix process implementation to understand when posix_spawn is unavailable, then investigate how a solution could preserve parent-death, file-descriptor, and process-group semantics. Done means command-launch cost no longer scales materially with the app-server’s mappings, supported by profiling or benchmarking.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- operating-systems, performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100