tags:

views:

481

answers:

3

We are using APC as an opcode cache. Is there a way to get APC to cache the non-existence of a file? We have set apc.stat = 0 and apc.include_once_override = 1. Is there something more to do to improve the performance of calling include_once on a file that may not be present on the filesystem? If it is present, obviously we want to include it. However, if it is not present, it will never be present and we don't want PHP to call open() on the file on every request to check.

For some background: we have one base site but provide customizations to the site on a customer-by-customer basis. Some customers have a custom login page, others have totally unique pages, etc.

We're using the Zend Framework in a slightly unusual way to allow us to override controllers as necessary. Our site might have a controller called LoginController, defined in a file controllers/LoginController.php. However, our client "Company" might have a requirement for a custom login page, so we will write a new class called Company_LoginController defined in a directory controllers/company/LoginController.php. (This naming convention allows us to be consistent with the Zend Framework notion of "modules".)

When we're dealing with the class, we basically do something like this:

include_once APPLICATION_PATH . '/controllers/company/LoginController.php';
if (class_exists("Company_LoginController")) {
    echo 'customer-specific controller exists';
} else {
    include_once APPLICATION_PATH . '/controllers/LoginController.php';
    echo 'customer-specific controller does not exist; using default';
}

If the file /controllers/company/LoginController.php exists, APC will cache it on the first request and never fetch it from the filesystem again. However, if the file /controllers/company/LoginController.php does not exist, I don't want APC to check for the existence of this file more than once. Any way to make this happen?

+3  A: 

Can you just create empty files in the company directory? Since APC will not load them twice, there's no harm in having some empty files that get "loaded" the first time the server starts.

jmucchiello
If, for some reason, leaving empty files around is undesirable, you could even potentially temporarily create the empty file, force compilation with apc_compile_file (or, probably, a simple include), and then delete the temporary file. But that'd be a bit of a hack.
Frank Farmer
Ah, this is a posibility that I hadn't thought of (creating the file on the fly, including it, then deleting it again). Not sure how well it'll go over on the other devs though, as it is a bit of a hack...
I admit, the idea of shipping empty files seems wrong. But any solution for creating files on the fly will also involve more code. That code will involve calls to file_exists() and I assume the point of using APC is to avoid those calls. You also run might into an issue is there is a call to clearstatcache (I don't know if APC using that cache or not).
jmucchiello
+2  A: 

jmucchiello's answer gets my vote for simplicity, but if for some reason that's not practical, you could always do things the hard way.

The following is a rough, untested example, but it should communicate the basic idea, which is to manually store the existence of the file in APC yourself

function conditional_include($file) {
  $key = 'file-exists-' . $file;
  //fetch cache key; if it does not exist, then...
  if(($fileExists = apc_fetch($key)) === false) {
    //actually hit the disk to look for the file, and store the result
    apc_store($key, $fileExists = (file_exists($file) ? 1 : 0));
  }

  //only include the file if it exists.
  if($fileExists)
   include_once $file;
}
Frank Farmer
A: 

If you are using Zend Framework i would recommend using using the Zend_Loader autoloading magic to make sure the files you need are loaded. By using the autoloader you can strip out nearly all the include_once calls from ZF (except the ones in the Zend_Loader class) Caveat - does depend on your class and filenaming style, but you can rewrite/extend the autoloader to counter this.

This might not be what you are after but i hope its helpful nonetheless..

James Butler