Excessive File I/O
debt(d5/e3/b5/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list Blackfire, strace, and Xdebug — all specialist profiling/tracing tools. The pattern (config file read every request, file_exists in loops) is not caught by a standard linter and won't surface as a compiler error; it requires profiling under load or explicit syscall tracing with strace to quantify.
Closest to 'simple parameterised fix' (e3). The quick_fix specifies caching file reads in APCu or Redis after the first request — a targeted replacement of repeated disk calls with a cache layer. This touches the specific read sites (e.g. wrapping file_get_contents with an APCu check) rather than a single one-liner (e1), but doesn't require a cross-cutting refactor — it's a small, localised pattern replacement.
Closest to 'persistent productivity tax' (b5). applies_to covers both web and cli contexts in PHP, meaning the pattern can appear across many parts of a codebase (request handlers, CLI scripts, middleware). Once file reads are scattered throughout the codebase without caching, every new feature touching config or shared data risks reintroducing the problem, slowing down multiple work streams, but it doesn't fully define the system's shape.
Closest to 'serious trap' (t7). The misconception field states explicitly: 'File I/O is fast enough that it rarely causes performance issues in PHP.' This directly contradicts the reality that file I/O is orders of magnitude slower than memory access. A competent developer familiar with other fast I/O abstractions (e.g. in-memory config patterns in other frameworks) may still assume PHP file reads are cheap, especially for small files. This is a well-documented but widely misapplied gotcha that contradicts intuitions built from working with modern caching-by-default frameworks.
Also Known As
TL;DR
Explanation
File I/O is orders of magnitude slower than memory access. Reading a file once per request is fine; reading the same file inside a loop that runs 100 times per request multiplies the I/O cost 100×. The standard fix is a static cache: static $cache = []; if (!isset($cache[$key])) { $cache[$key] = file_get_contents($path); } return $cache[$key]; The first read hits disk; subsequent reads return the cached value instantly.
Common Misconception
Why It Matters
Common Mistakes
- Reading configuration files on every request instead of loading once at startup.
- Not caching file_get_contents() results for files that rarely change.
- Writing to log files synchronously on every request — use async logging or a buffer.
- Checking file_exists() in loops — each call is a filesystem syscall.
Code Examples
// Reading the same file on every request inside a loop
foreach ($userIds as $id) {
$config = file_get_contents('/etc/app/config.json'); // disk hit every iteration
$cfg = json_decode($config, true);
process($id, $cfg);
}
// Read once, reuse in memory
$cfg = json_decode(file_get_contents('/etc/app/config.json'), true);
foreach ($userIds as $id) {
process($id, $cfg);
}
// For cross-request reuse: OPcache can cache PHP arrays returned from files
// config/cache.php → return [...]; and use opcache_invalidate() on change