[ACCEPTED]-Why is require_once so bad to use?-require-once

Accepted answer
Score: 148

This thread makes me cringe, because there's 61 already been a "solution posted", and 60 it's, for all intents and purposes, wrong. Let's 59 enumerate:

  1. Defines are really expensive in PHP. You 58 can look it up or test it yourself, but the only efficient 57 way of defining a global constant in PHP 56 is via an extension. (Class constants are 55 actually pretty decent performance wise, but 54 this is a moot point, because of 2)

  2. If you 53 are using require_once() appropriately, that is, for inclusion 52 of classes, you don't even need a define; just 51 check if class_exists('Classname'). If the file you are including 50 contains code, i.e. you're using it in the 49 procedural fashion, there is absolutely 48 no reason that require_once() should be necessary for 47 you; each time you include the file you 46 presume to be making a subroutine call.

So 45 for a while, a lot of people did use the 44 class_exists() method for their inclusions. I don't like 43 it because it's fugly, but they had good 42 reason to: require_once() was pretty inefficient before 41 some of the more recent versions of PHP. But 40 that's been fixed, and it is my contention 39 that the extra bytecode you'd have to compile 38 for the conditional, and the extra method 37 call, would by far overweigh any internal 36 hashtable check.

Now, an admission: this 35 stuff is tough to test for, because it accounts 34 for so little of the execution time.

Here 33 is the question you should be thinking about: includes, as 32 a general rule, are expensive in PHP, because 31 every time the interpreter hits one it has 30 to switch back into parse mode, generate 29 the opcodes, and then jump back. If you 28 have a 100+ includes, this will definitely 27 have a performance impact. The reason why 26 using or not using require_once is such 25 an important question is because it makes 24 life difficult for opcode caches. An explanation for this can 23 be found here, but what this boils down 22 to is that:

  • If during parse time, you know 21 exactly what include files you will need 20 for the entire life of the request, require() those 19 at the very beginning and the opcode cache 18 will handle everything else for you.

  • If you 17 are not running an opcode cache, you're 16 in a hard place. Inlining all of your includes 15 into one file (don't do this during development, only 14 in production) can certainly help parse 13 time, but it's a pain to do, and also, you 12 need to know exactly what you'll be including 11 during the request.

  • Autoload is very convenient, but 10 slow, for the reason that the autoload logic 9 has to be run every time an include is done. In 8 practice, I've found that autoloading several 7 specialized files for one request does not 6 cause too much of a problem, but you should 5 not be autoloading all of the files you 4 will need.

  • If you have maybe 10 includes 3 (this is a very back of the envelope calculation), all 2 this wanking is not worth it: just optimize 1 your database queries or something.

Score: 114

require_once and include_once both require that the system keeps 18 a log of what's already been included/required. Every 17 *_once call means checking that log. So there's 16 definitely some extra work being done there 15 but enough to detriment the speed of the 14 whole app?

... I really doubt it... Not unless 13 you're on really old hardware or doing it a lot.

If 12 you are doing thousands of *_once, you could do the 11 work yourself in a lighter fashion. For 10 simple apps, just making sure you've only 9 included it once should suffice but if you're 8 still getting redefine errors, you could 7 something like this:

if (!defined('MyIncludeName')) {
    require('MyIncludeName');
    define('MyIncludeName', 1);
}

I'll personally stick 6 with the *_once statements but on silly million-pass 5 benchmark, you can see a difference between 4 the two:

                php                  hhvm
if defined      0.18587779998779     0.046600103378296
require_once    1.2219581604004      3.2908599376678

10-100× slower with require_once and it's curious 3 that require_once is seemingly slower in hhvm. Again, this 2 is only relevant to your code if you're 1 running *_once thousands of times.


<?php // test.php

$LIMIT = 1000000;

$start = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    if (!defined('include.php')) {
        require('include.php');
        define('include.php', 1);
    }

$mid = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    require_once('include.php');

$end = microtime(true);

printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);

<?php // include.php

// do nothing.
Score: 68

I got curious and checked out Adam Backstrom's 65 link to Tech Your Universe. This article describes one of 64 the reasons that require should be used 63 instead of require_once. However, their 62 claims didn't hold up to my analysis. I'd 61 be interested in seeing where I may have 60 misanalysed the solution. I used PHP&nbsp;5.2.0 59 for comparisons.

I started out by creating 58 100 header files that used require_once 57 to include another header file. Each of 56 these files looked something like:

<?php
    // /home/fbarnes/phpperf/hdr0.php
    require_once "../phpperf/common_hdr.php";

?>

I created 55 these using a quick Bash hack:

for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
    echo "<?php
    // $i" > $i
    cat helper.php >> $i;
done

This way I 54 could easily swap between using require_once 53 and require when including the header files. I 52 then created an app.php to load the one 51 hundred files. This looked like:

<?php
    // Load all of the php hdrs that were created previously
    for($i=0; $i < 100; $i++)
    {
        require_once "/home/fbarnes/phpperf/hdr$i.php";
    }

    // Read the /proc file system to get some simple stats
    $pid = getmypid();
    $fp = fopen("/proc/$pid/stat", "r");
    $line = fread($fp, 2048);
    $array = split(" ", $line);

    // Write out the statistics; on RedHat 4.5 with kernel 2.6.9
    // 14 is user jiffies; 15 is system jiffies
    $cntr = 0;
    foreach($array as $elem)
    {
        $cntr++;
        echo "stat[$cntr]: $elem\n";
    }
    fclose($fp);
?>

I contrasted 50 the require_once headers with require headers 49 that used a header file looking like:

<?php
    // /home/fbarnes/phpperf/h/hdr0.php
    if(!defined('CommonHdr'))
    {
        require "../phpperf/common_hdr.php";
        define('CommonHdr', 1);
    }
?>

I didn't 48 find much difference when running this with 47 require vs. require_once. In fact, my initial 46 tests seemed to imply that require_once 45 was slightly faster, but I don't necessarily 44 believe that. I repeated the experiment 43 with 10000 input files. Here I did see a 42 consistent difference. I ran the test multiple 41 times, the results are close but using require_once 40 uses on average 30.8 user jiffies and 72.6 39 system jiffies; using require uses on average 38 39.4 user jiffies and 72.0 system jiffies. Therefore, it 37 appears that the load is slightly lower 36 using require_once. However, the wall clock 35 time is slightly increased. The 10,000 require_once 34 calls use 10.15 seconds to complete on average 33 and 10,000 require calls use 9.84 seconds 32 on average.

The next step is to look into 31 these differences. I used strace to analyse the 30 system calls that are being made.

Before 29 opening a file from require_once the following 28 system calls are made:

time(NULL)                              = 1223772434
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0
time(NULL)                              = 1223772434
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

This contrasts with 27 require:

time(NULL)                              = 1223772905
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
time(NULL)                              = 1223772905
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Tech Your Universe implies that 26 require_once should make more lstat64 calls. However, they 25 both make the same number of lstat64 calls. Possibly, the 24 difference is that I am not running APC 23 to optimize the code above. However, next 22 I compared the output of strace for the 21 entire runs:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190709 strace_1000r.out
  210707 strace_1000ro.out
  401416 total

Effectively there are approximately 20 two more system calls per header file when 19 using require_once. One difference is that 18 require_once has an additional call to the 17 time() function:

[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008

The other system call is 16 getcwd():

[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004

This is called because I decided 15 to relative path referenced in the hdrXXX 14 files. If I make this an absolute reference, then 13 the only difference is the additional time(NULL) call 12 made in the code:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190705 strace_1000r.out
  200705 strace_1000ro.out
  391410 total
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20008
strace_1000ro.out:30008

This seems to imply that 11 you could reduce the number of system calls 10 by using absolute paths rather than relative 9 paths. The only difference outside of that 8 is the time(NULL) calls which appear to 7 be used for instrumenting the code to compare 6 what is faster.

One other note is that the 5 APC optimization package has an option called 4 "apc.include_once_override" that 3 claims that it reduces the number of system 2 calls made by the require_once and include_once 1 calls (see the PHP documentation).

Score: 22

Can you give us any links to these coding 10 practices which say to avoid it? As far 9 as I'm concerned, it's a complete non-issue. I haven't looked at 8 the source code myself, but I'd imagine 7 that the only difference between include and include_once is 6 that include_once adds that filename to an array and 5 checks over the array each time. It'd be 4 easy to keep that array sorted, so searching 3 over it should be O(log n), and even a medium-largish 2 application would only have a couple of 1 dozen includes.

Score: 7

A better way to do things is to use an object-oriented 1 approach and use __autoload().

Score: 6

The *_once() functions stat every parent directory to 7 ensure the file you're including isn't the 6 same as one that's already been included. That's 5 part of the reason for the slowdown.

I recommend 4 using a tool like Siege for benchmarking. You 3 can try all the suggested methodologies 2 and compare response times.

More on require_once() is at 1 Tech Your Universe.

Score: 6

The PEAR2 wiki (when it existed) used to 6 list good reasons for abandoning all the require/include directives in favor of autoloading, at least for library code. These 5 tie you down to rigid directory structures 4 when alternative packaging models like phar are 3 on the horizon.

Update: As the web archived 2 version of the wiki is eye-gougingly ugly, I've 1 copied the most compelling reasons below:

  • include_path is required in order to use a (PEAR) package. This makes it difficult to bundle a PEAR package within another application with its own include_path, to create a single file containing needed classes, to move a PEAR package to a phar archive without extensive source code modification.
  • when top-level require_once is mixed with conditional require_once, this can result in code that is uncacheable by opcode caches such as APC, which will be bundled with PHP 6.
  • relative require_once requires that include_path already be set up to the correct value, making it impossible to use a package without proper include_path
Score: 6

It's not using the function that is bad. It's 52 an incorrect understanding of how and when 51 to use it, in an overall code base. I'll 50 just add a bit more context to that possibly 49 misunderstood notion:

People shouldn't think 48 that require_once is a slow function. You 47 have to include your code one way or another. require_once() vs. require()'s 46 speed isn't the issue. It's about the performance 45 hindering caveats that may results for using 44 it blindly. If used broadly without consideration 43 for context, it can lead to huge memory 42 waste or wasteful code.

What I have seen 41 that's really bad, is when huge monolithic 40 frameworks use require_once() in all the wrong ways, especially 39 in a complex object-oriented (OO) environment.

Take 38 the example of using require_once() at the top of every 37 class as seen in many libraries:

require_once("includes/usergroups.php");
require_once("includes/permissions.php");
require_once("includes/revisions.php");
class User{
  // User functions
}

So the User class 36 is designed to use all three other classes. Fair 35 enough!

But now what if a visitor is browsing 34 the site and not even logged in and the 33 framework loads: require_once("includes/user.php"); for every single request.

It's 32 including 1+3 unnecessary classes it won't ever use 31 during that particular request. This is 30 how bloated frameworks end up using 40 MB 29 per request as opposed to 5 MB or less.


The 28 other ways it can be misused, is when a 27 class is re-used by many others! Say you 26 have about 50 classes that use helper functions. To 25 make sure helpers are available for those classes 24 when they are loaded, you get:

require_once("includes/helpers.php");
class MyClass{
  // Helper::functions(); // etc..
}

There is nothing 23 wrong here per se. However if one page request 22 happens to include 15 similar classes. You 21 are running require_once 15 times, or for a nice visual:

require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");

The 20 use of require_once() technically affects 19 performance for running that function 14 18 times, on top of having to parse those unnecessary 17 lines. With just 10 other highly used classes 16 with that similar problem, it could account 15 for 100+ lines of such rather pointless 14 repetitive code.

With that, it's probably 13 worth using require("includes/helpers.php"); at the bootstrap of your application 12 or framework, instead. But since everything 11 is relative, it all depends if the weight versus usage 10 frequency of the helpers class is worth saving 9 15-100 lines of require_once(). But if the probability 8 of not using the helpers file on any given request 7 is none, then require should definitely be in your 6 main class instead. Having require_once in each class 5 separately becomes a waste of resources.


The 4 require_once function is useful when necessary, but 3 it shouldn't be regarded as a monolithic 2 solution to use everywhere for loading all 1 classes.

Score: 3

Even if require_once and include_once are slower than require and include (or whatever 15 alternatives might exist), we're talking 14 about the smallest level of micro-optimization 13 here. Your time is much better spent optimizing 12 that poorly written loop or database query 11 than worrying about something like require_once.

Now, one 10 could make an argument saying that require_once allows 9 for poor coding practices because you don't 8 need to pay attention to keeping your includes 7 clean and organized, but that has nothing 6 to do with the function itself and especially 5 not its speed.

Obviously, autoloading is 4 better for the sake of code cleanliness 3 and ease of maintenance, but I want to make 2 it clear that this has nothing to do with 1 speed.

Score: 0

You test, using include, oli's alternative 2 and __autoload(); and test it with something like APC installed.

I 1 doubt using constant will speed things up.

Score: 0

Yes, it is slightly more expensive than 8 plain ol' require(). I think the point is 7 if you can keep your code organized enough 6 to not duplicate includes, don't use the 5 *_once() functions, as it will save you 4 some cycles.

But using the _once() functions 3 isn't going to kill your application. Basically, just 2 don't use it as an excuse to not have to organize your includes. In some cases, using it is still unavoidable, and 1 it's not a big deal.

More Related questions