Performance: Excessive file I/O - Changelog read 18x/sec, uncached OAuth, subprocess overhead

Resolved 💬 5 comments Opened Jan 20, 2026 by vmitro Closed Feb 27, 2026

Summary

Profiling Claude Code with strace reveals several I/O inefficiencies that contribute to high CPU/memory usage.

Background

While investigating OOM issues with Claude Code (observed 1.6GB memory usage for a single process), I ran strace to understand the I/O patterns. At the time, Claude Code was performing git operations - specifically checking out individual files from a previous working commit and comparing them against the current HEAD state on a private repository.

Disclaimer

This 38-second strace capture is a limited sample and may not provide complete insight into all I/O or memory issues. However, we hope the patterns identified here are indicative and helpful for future optimization efforts.

Environment

  • Claude Code version: 2.1.x (latest)
  • Platform: WSL2 / Linux (kernel 6.6.87.2-microsoft-standard-WSL2)
  • Profiling command: sudo strace -f -tt -p 52212 -e trace=read,open,stat > claude_strace.txt 2>&1
  • Duration: ~38 seconds of normal git-related operation

Findings

1. CHANGELOG.md read 18x/second (5.5 MB in 38s)

The changelog file is being read repeatedly at ~8KB per read, totaling 683 reads and 5.5 MB in 38 seconds. This appears to happen on every operation cycle.

Changelog_md: 683 reads, 5,450,686 bytes total
🔴 WASTEFUL: Reading entire changelog ~8KB per read!

Suggestion: Cache changelog content in memory or read once at startup.

2. OAuth credentials read from disk repeatedly (1.7x/sec)

Credentials file is re-read from ~/.claude/.credentials.json ~64 times in 38 seconds instead of being cached in memory.

OAuth_credentials: 64 reads, 27,712 bytes total (433 bytes each)

Suggestion: Cache credentials in memory, only re-read on auth failure or file change (inotify).

3. Excessive subprocess spawning (83 in 38s)

Each subprocess (mostly git commands) incurs:

  • ELF binary loads (74 reads, 62KB)
  • Locale alias loading (35 reads, 105KB)
  • Shell profile/bashrc reads (26 reads, 56KB)
  • Git config reads
⚠️ Subprocess overhead:
   83 subprocesses spawned in 37.7s
   74 ELF binary loads, 35 locale file reads

Suggestion: Batch git operations, use git plumbing commands that can return multiple pieces of info, or consider a long-running git helper process.

4. Unbuffered single-byte pipe reads (573 reads)

Reading from pipes one byte at a time instead of buffered reads.

single_char_unbuffered: 573 reads, 573 bytes total
🔴 587 single-byte reads! Use buffered I/O

Suggestion: Use buffered I/O for pipe reading.

Full Profile Output

Time range: 38 seconds of git-related operation
Total read() calls: 2,146
Total bytes read: 5.68 MB
Read frequency: 57.0 reads/sec

BY CONTENT TYPE (sorted by read count)
Type                              Count        Bytes
Changelog_md                        683    5,450,686
single_char_unbuffered              573          573
empty/EOF                           385            0
ELF_binary                           74       61,568
OAuth_credentials                    64       27,712
binary_inotify_epoll                 48          496
git_HEAD                             42          966
locale_alias                         35      104,860
gitconfig_user                       29        2,349
git_config                           28        8,789
shell_config                         26       55,984
settings_json                        24      155,838
TLS_traffic                          13       31,108
TLS_handshake                         6        7,232

Profiler Script

We wrote a Python script to parse and categorize strace output - happy to share if useful for internal profiling.

Impact

These inefficiencies compound over time, especially in long sessions, and likely contribute to the high memory usage (1.6GB observed for a single Claude Code process) and general system load.

---

<sub>© 2026. This issue content is provided to Anthropic for bug reporting purposes only. Reproduction or use in derivative content (videos, articles, social media) without explicit written permission is prohibited.</sub>

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗