Tue Oct 24 02:43:17 PHT 2006 Nimrod A. Abing * Implement lazy loading of model classes. This patch will modify model loading behavior so that only those models that are actually used are loaded. Rationale: This is a performance enhancement. In the mainstream implementation, loadModels() will load all model class files that it finds in the models folder. In many cases only a few of these models are actually used. Unused models waste not only memory and parsing and compiling time, but also produce extra overhead incurred when those unused class files are opened for reading. In the worst case, the server could run into file handle exhaustion errors. Full Explanation: This patch is backward compatible with mainstream CakePHP. It adds the ability to load model class files only when needed. In order for a class file to be lazy loaded, it must be placed in the app/models/lazy_load folder. Class files under app/models are loaded as usual. This patch should also work with plugins as well. diff -rN -u old-cake/cake/basics.php new-cake/cake/basics.php --- old-cake/cake/basics.php 2006-10-24 02:44:20.000000000 +0800 +++ new-cake/cake/basics.php 2006-10-24 02:44:20.000000000 +0800 @@ -160,6 +160,21 @@ return false; } /** + * Loads a model by CamelCase name from the lazy_load models directory. + */ + function lazyLoadModel($name) { + $name = Inflector::underscore($name); + $paths = Configure::getInstance(); + + foreach($paths->modelPaths as $path) { + if (file_exists($path . 'lazy_load' . DS . $name . '.php')) { + require($path . 'lazy_load' . DS . $name . '.php'); + return true; + } + } + return false; + } +/** * Loads all controllers. */ function loadControllers() { diff -rN -u old-cake/cake/libs/controller/controller.php new-cake/cake/libs/controller/controller.php --- old-cake/cake/libs/controller/controller.php 2006-10-24 02:44:20.000000000 +0800 +++ new-cake/cake/libs/controller/controller.php 2006-10-24 02:44:20.000000000 +0800 @@ -303,6 +303,9 @@ $cached = false; $object = null; + if (!class_exists($this->modelClass)) { + lazyLoadModel($this->modelClass); + } if (class_exists($this->modelClass) && ($this->uses === false)) { if ($this->persistModel === true) { $cached = $this->_persist($this->modelClass, null, $object); @@ -337,6 +340,10 @@ $object = null; $modelKey = Inflector::underscore($modelClass); + if (!class_exists($modelClass)) { + lazyLoadModel($modelClass); + } + if (class_exists($modelClass)) { if ($this->persistModel === true) { $cached = $this->_persist($modelClass, null, $object); @@ -781,6 +788,9 @@ $modelName = $relData['className']; $manyAssociation = $relation; $modelKeyM = Inflector::underscore($modelName); + if (!class_exists($modelName)) { + lazyLoadModel($modelName); + } $modelObject =& new $modelName(); if ($doCreateOptions) { diff -rN -u old-cake/cake/libs/model/model_php4.php new-cake/cake/libs/model/model_php4.php --- old-cake/cake/libs/model/model_php4.php 2006-10-24 02:44:20.000000000 +0800 +++ new-cake/cake/libs/model/model_php4.php 2006-10-24 02:44:20.000000000 +0800 @@ -457,6 +457,9 @@ if (ClassRegistry::isKeySet($colKey)) { $this->{$className} =& ClassRegistry::getObject($colKey); } else { + if (!class_exists($className)) { + lazyLoadModel($className); + } $this->{$className} =& new $className(); } diff -rN -u old-cake/cake/libs/model/model_php5.php new-cake/cake/libs/model/model_php5.php --- old-cake/cake/libs/model/model_php5.php 2006-10-24 02:44:20.000000000 +0800 +++ new-cake/cake/libs/model/model_php5.php 2006-10-24 02:44:20.000000000 +0800 @@ -451,6 +451,9 @@ if (ClassRegistry::isKeySet($colKey)) { $this->{$className} = ClassRegistry::getObject($colKey); } else { + if (!class_exists($className)) { + lazyLoadModel($className); + } $this->{$className} = new $className(); }