Профилирование Joomla при помощи xdebug на PHP 5.2.4 показало два следующих «слабых места»:
- метод JRegistryFormatINI::stringToObject (файл /libraries/joomla/registry/format/ini.php), выполняющий парсинг данных в формате ini-файла, и
- метод JLoader::load (файл /libraries/loader.php; в дальнейшем имена файлов указывать не буду, надеюсь найти, что и где лежит не является проблемой), вызываемый из функции __autoload для автоматического подключения файла нужного класса.
Какие могут быть методы борьбы с этими «тормозами»? Начнем по-порядку.
1. Метод JRegistryFormatINI::stringToObject
1.1. Можно попробовать переписать этот метод с целью ускорить быстродействие. Основные идеи, которые могут ускорить его работу, следующие:
— В процессе работы метода в цикле регулярно проверяется условие if($process_sections), проверку которого можно вынести за пределы цикла.
— Функция проверяет только наличие комментариев, начинающихся с «;», в то время как в действительности комментарии в языковых ini-файлах начинаются с «#». Проверка такого условия уберет лишние операции с этими строками.
— Тест показал, что вместо strpos/substr быстрее разбить строку на две части при помощи explode.
— Результат для strpos-поиска «|» можно запомнить и впоследствии не делать лишний str_replace.
— В preg_match и preg_split желательно использовать одинаковые ограничители регулярных выражений — это уберет дополнительный парсинг и компиляцию второго выражения.
— Условие того, что значением параметра является массив проще записать в виде $array = count($parts)>1, а не в виде сравнения строк.
— Разбиение аргумента на строки выполняется даже в том случае, когда готовый ответ уже есть в $inistocache. Зачем?
Итого удается увеличить скорость работы этой функции на 19%.
Конкретный вид модификаций не привожу — их и так можно посмотреть в прилагаемом архиве, сравнивая с оригигинальными файлами.
1.2. Анализ передаваемых аргументов показал, что при отрисовке модулей их параметры передаются этому методу дважды: один раз в методе JDocumentRendererModule::render, а второй — в вызываемом из него методе JModuleHelper::renderModule. И хотя второй вызов выполняется значительно быстрее, т.к. результат первого вызова сохранен в $inistocache, было бы логично этого вызова избежать. Для этого достаточно передавать параметры модуля третьим аргументом в JModuleHelper::renderModule.
1.3. Львиную долю всех вызовов занимает парсинг языковых файлов. Т.к. эти файлы не меняются от вызова к вызову, имеет смысл кэшировать результаты парсинга. Для этого достаточно внести модификацию в JLanguage::_load. По-хорошему, было бы логичным сделать время жизни этого «языкового» кэша также настраиваемым из админки, но пока пусть оно будет таким же как и для всего сайта.
2. Метод JLoader::load.
2.1. В самом методе strtolower вызывается дважды. Второй вызов явно лишний.
2.2. JLoader::register возвращает ссылку, поэтому заменяем присваивание на =&.
2.3. Так как больше всего времени занимает include файлов, то имеет смысл вынести объявление самых часто-используемых файлов в один файл и подключать его сразу при запуске. К сожалению, не для всех классов такое возможно, но прирост в скорости будет все-равно заметным. Для построения такого файла достаточно вызвать прилагаемый скрипт /cache.php и сделать небольшую модификацию /index.php (те файлы, которые нельзя переносить в другое место, закомментированы в тексте скрипта).
Во вложении ниже приведены все пропатченные файлы и скрипт создания файла с глобальным описанием классов cache.php.
PS. Хочу отправить это разработчикам Joomla!, поэтому жду вашей критики / комментариев / замечаний.
PPS. Кто б еще подсказал, в какой раздел лучше перекинуть эту тему.
[вложение удалено Администратором]