So, I've been reading articles for a decade now that say that readfile()
is great and wonderful except for memory usage. Specifically, that it
reads a file into memory entirely, and then prints it to stdout from
there. So if you're outputing a big file you will hit your memory limit
and kill the server. Thus, one should always loop over fread()
instead. The most recent article I found saying that was from 2007,
with a StackExchange thread saying the same from 2011. I've even found
mention of it in old PHP Bugs.
However, I cannot replicate that in my own testing. Earlier today I was
running some benchmarks of different file streaming techniques in PHP
(5.3.6 specifically) and found that fread() looping, fpassthru(),
readfile(), and stream_copy_to_stream() perform almost identically on
memory, and all are identical on CPU except for fread() which is slower,
which makes sense since you're looping in PHP space.
What's more, I cranked my memory limit down to 10 MB and then tried
streaming a 20 MB file. No change. The PHP peak memory never left
around a half-meg or so, most of which I presume is just the Apache/PHP
overhead. But it's not actually possible for readfile() to be buffering
the whole file into memory before printing and not die if the file is
bigger than the memory limit. I verified that the data I'm getting
downloaded from the script is correct, and exactly matches the file that
it should be streaming.
My first thought was that this is yet another case of PHP improving and
fixing a long-standing bug, but somehow the rest of the world not
knowing about it so "conventional wisdom" persists long after it's still
wise. However, I found no mention of readfile() in the PHP 5 change
log[1] at all aside from one note from back in 5.0.0 Beta 1 about
improving performance under Windows. (I'm on Linux.)
So, what's going on here? Has readfile() been memory-safe for that long
without anyone noticing? Is my test completely flawed (although I don't
see how since I can verify that the code works as expected)? Something
else?
Please un-confuse me!
(Note: Sending this to internals since this is an engine question, and I
am more likely to reach whoever it was that un-sucked readfile()
sometime in the silent past that way. <g>)
--Larry Garfield
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php