openai / openai/codex

Unix app-server: fork/exec becomes CPU-bound after memory growth

Open
#42,738 0 comments 11 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug performance
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:

https://github.com/openai/codex/blob/3c837e568c24e4281bba4abdf3bc3c398f3fff13/codex-rs/core/src/spawn.rs#L94-L116

https://github.com/openai/codex/blob/3c837e568c24e4281bba4abdf3bc3c398f3fff13/codex-rs/utils/pty/src/pipe.rs#L155-L168

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);
}

Source: https://github.com/rust-lang/rust/blob/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/process/unix/unix.rs#L460-L468

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.