tags:

views:

392

answers:

6

have a file caching system for a php 5 library i use often. when the request is made i check for a cached file, if there is one i render it and exit.

$contents = file_get_contents( self::_cacheFile() );
echo $contents;
exit();     

i have to do file_get_contents instead of just include because of cached xml files with the pesky

`<?xml version="1.0"?>` 

is there a better way to pull in my cache files without shorttags firing?

+5  A: 

Since include will evaluate the content of the files, e.g. run in through the PHP interpreter and also use the include_path to find files, I'd say include is slower. file_get_contents will just treat the contents of a file as string. Less overhead, more speed.

From the manual page:

file_get_contents() is the preferred way to read the contents of a file into a string. It will use memory mapping techniques if supported by your OS to enhance performance.

However, if you are after outputting the file, instead of getting it into a string, readfile() is even a tiny bit faster than file_get_contents. Given that include'ing will output any non PHP content as well, this likely more likely what you are after I guess.

Revised benchmark on my desktop machine:

$start1 = microtime(1);
for($i=0; $i<100000; $i++) {
    include 'log.txt';
}
$end1 = microtime(1) - $start1;

and

$start2 = microtime(1);
for($i=0; $i<100000; $i++) {
    echo file_get_contents('log.txt');
}
$end2 = microtime(1) - $start2;

and

$start3 = microtime(1);
for($i=0; $i<100000; $i++) {
    readfile('log.txt');
}
$end3 = microtime(1) - $start3;

Result

echo PHP_EOL, $end1, // 137.577358961
     PHP_EOL, $end2, // 136.229552984
     PHP_EOL, $end3; // 136.849179029
Gordon
great thanks for your opinion, i was under the impression that include was faster, good i dont need to change anything then
David Morrow
Was just going to post something similar -- you covered it nicely. +1
henasraf
@Gordon you are forgetting the echo call in your second script. Do echo(file_get_contents('log.txt'))
Vinko Vrsalovic
@Vinko actually I left it out on purpose to just see how file_get_contents performed, but I did the test with echo as well and there is no difference.
Gordon
@Gordon because you are discarding the output with ob_end_clean(). Real output takes time you are not considering.
Vinko Vrsalovic
@Vinko But the output should be the same for both. Feel free to let the test run 100000 times on your machine without output buffering. That would take hours :)
Gordon
@Gordon: I did so, check my answer... I just discarded the output via redirecting to /dev/null, that way the output is actually done and not discarded inside the php engine.
Vinko Vrsalovic
@Vinko ok, but it still shouldn't make a difference when I discard the output for all test cases, shouldn't it? I mean, outputting should take the same time, regardless of include or file_get_contents (or readfile for that matter), right?
Gordon
@Gordon: Not necessarily, the code paths for a direct echo() and for a function that does it itself are probably different.
Vinko Vrsalovic
@Vinko Granted, but readfile outputs by itself too and it performs almost the same as file_get_contents. I'd say it's a micro-optimization anyway and the more important question is when to use which.
Gordon
@Gordon: I'm not disputing the correctness of using readfile() (that's what it is for). I'm just disputing the correctness of your benchmark. In mine (which I think is better than yours :-) the three alternatives perform very similarly. Now, I might be overlooking something, for sure.
Vinko Vrsalovic
@Vinko updated and revised and - yes - they perform equal. You win ;)
Gordon
+4  A: 

file_get_contents and include don't do the same thing :

  • file_get_contents reads the content of a file, and returns it as a string
  • include will execute the content of the file.

About the speed, without an opcode cache, I suppose file_get_contents should theorically be faster, as it does less calculation (no compilation/execution of the code).


Still, what matters the most is probably what you are trying to do : if you only want to read a file, you should use file_get_contents.

Pascal MARTIN
But marginally so, as there is no code in the files...
Vinko Vrsalovic
+2  A: 

Nothing beats a (well made) benchmark (which is harder than it looks, I might be overlooking something). Still as both are made in the same conditions they should serve as a measuring stick.

test.txt is a 12kB, 876 lines text file:

vinko@parrot:~$ ls -la test.txt ; wc -l test.txt
-rw-r--r-- 1 vinko vinko 12264 2010-02-24 19:08 test.txt
876 test.txt

file_get_contents.php:

vinko@parrot:~$ more file_get_contents.php
<?php
echo file_get_contents("test.txt");
?>

include.php

vinko@parrot:~$ more include.php
<?php
include("test.txt");
?>

readfile.php

vinko@parrot:~$ more readfile.php
<?php
readfile("test.txt");
?>

So, we time the execution of 10 thousand iterations of each:

vinko@parrot:~$ time for i in `seq 10000`; do php file_get_contents.php >/dev/null; done

real    3m57.895s
user    2m35.380s
sys     1m15.080s

vinko@parrot:~$ time for i in `seq 10000`; do php include.php >/dev/null; done

real    3m57.919s
user    2m37.040s
sys     1m16.780s

vinko@parrot:~$ time for i in `seq 10000`; do php readfile.php >/dev/null; done 
real    3m57.620s
user    2m38.400s
sys     1m14.100s

Conclusion: All three are practically equivalent for 12 kB text files on PHP 5.2.4 with Suhosin Patch.

Vinko Vrsalovic
that should be `echo $contents;` without the `()`. Also `readfile` writes to the output buffer directly and return an integer, so no need to echo this. Just call `readfile`. You don't need the `exit` calls either.
Gordon
@Gordon: Thanks, changed the scripts and retested. Even more equal :)
Vinko Vrsalovic
A: 

file_get_contents will be the fastest way to retrieve the cached file for a couple reasons:

  1. It performs no processing on the data it loads (parsing PHP code, handling newlines etc.)
  2. It uses optimized techniques to load the files as fast as possible (memory mapped files for one).
Jon Benedicto
+3  A: 

If all you want to do is output the file contents, you should be using readfile(). This is faster and less memory intensive than file_get_contents()

chris
+1  A: 

thanks for the tip, for those who are curious

readfile();
<!-- dynamic page rendered in 0.133193016052 seconds.-->
<!-- static page rendered in 0.00292587280273 seconds.-->

vs.

file_get_contents();
<!-- dynamic page rendered in 0.133193016052 seconds.-->
<!-- static page rendered in 0.00303602218628 seconds.-->

vs.

include();
<!-- dynamic page rendered in 0.133193016052 seconds.-->
<!-- static page rendered in 0.00348496437073 seconds.-->
David Morrow
A single execution is not enough for a benchmark, you have to iterate a lot
Vinko Vrsalovic
10% longer response time for static page. Now, what happens when you turn on an opcode cache? +1 for research.
TheJacobTaylor