Пострадает ли производительность при использовании автоматической загрузки в php и поиске файла класса?


Я всегда боролся с тем, как лучше всего включить классы в мой php-код. Обычно это проблема, но несколько минут назад я нашел этот вопрос, который значительно помогает в этом. Теперь я читаю о __ автозагрузке и думаю, что это может значительно упростить процесс разработки моих приложений. Проблема в том, что мне нравится поддерживать структуру папок для разделения областей функциональности, а не бросать все в общую папку/lib. Поэтому, если я переопределю автоматическую загрузку на выполните глубокий поиск в папке класса, включая все вложенные папки, какие показатели производительности я могу ожидать?

Очевидно, что это будет зависеть от масштаба, глубины структуры папок и количества классов, но в целом я спрашиваю о проекте среднего масштаба, вызовет ли это проблемы.

Author: Community, 2008-09-25

7 answers

__автоматическая загрузка - это здорово, но стоимость указания всех файлов в функции рекурсивного поиска стоит дорого. Возможно, вам захочется взглянуть на построение дерева файлов для автоматической загрузки. В моей структуре я последовательно называю файлы для их классов и использую карту, которая кэшируется для данных.

Выезд http://trac.framewerk.org/cgi-bin/trac.fcgi/browser/trunk/index.php [ мертвая ссылка] начиная со строки 68, чтобы получить представление о том, как это может быть сделано.

Редактировать: И чтобы более прямо ответить на ваш вопрос, без кэширования вы можете ожидать снижения производительности на сайте со средним и интенсивным трафиком.

 6
Author: Gavin M. Roy, 2010-04-15 12:15:46

Общий шаблон (Pear, Zend Framework в качестве примеров...) состоит в том, чтобы имя класса отражало путь, поэтому Db_Adapter_Mysql будет находиться в /Db/Adapter/Mysql.php, откуда-то, что добавлено в путь включения.

 5
Author: Greg, 2008-09-25 19:22:51

Есть 2 способа, которыми вы могли бы легко это сделать, прежде всего, назовите свои классы так, чтобы они определяли структуру того, где их найти

function __autoload($classname)
{
    try
    {
        if (class_exists($classname, false) OR interface_exists($classname, false))
        {
            return;
        }

        $class = split('_', strtolower(strval($classname)));

        if (array_shift($class) != 'majyk')
        {
            throw new Exception('Autoloader tried to load a class that does not belong to us ( ' . $classname . ' )');
        }

        switch (count($class))
        {
            case 1: // Core Class - matches Majyk_Foo - include /core/class_foo.php
                $file = MAJYK_DIR . 'core/class_' . $class[0] . '.php';
            break;

            case 2: // Subclass - matches Majyk_Foo_Bar - includes /foo/class_bar.php
                $file = MAJYK_DIR . $class[0] . '/class_' . $class[1] . '.php';
            break;

            default:
                throw new Exception('Unknown Class Name ( ' . $classname .' )');
                return false;
        }

        if (file_exists($file))
        {
            require_once($file);

            if (!class_exists($classname, false) AND !interface_exists($classname, false))
            {
                throw new Exception('Class cannot be found ( ' . $classname . ' )');
            }
        }
        else
        {
            throw new Exception('Class File Cannot be found ( ' . str_replace(MAJYK_DIR, '', $file) . ' )');
        }

    }
    catch (Exception $e)
    {
        // spl_autoload($classname);
        echo $e->getMessage();
    }

}

Или, 2, используйте несколько загрузчиков. PHP>=5.1.2 Имеет библиотеку SPL, которая позволяет добавлять несколько загрузчиков. Вы добавляете по одному для каждого пути, и он найдет его на своем пути. Или просто добавьте их в путь включения и используйте spl_autoload() по умолчанию

Пример

function autoload_foo($classname)
{
    require_once('foo/' . $classname . '.php');
}

function autoload_bar($classname)
{
    require_once('bar/' . $classname . '.php');
}

spl_autoload_register('autoload_foo');
spl_autoload_register('autoload_bar');
spl_autoload_register('spl_autoload'); // Default SPL Autoloader
 1
Author: Mez, 2008-09-25 20:34:22

Автозапуск - отличная функция PHP, которая вам очень поможет... Производительность не пострадала бы, если бы мы использовали интеллектуальную таксономию, такую как: 1. каждая библиотека остается в папках "пакеты". 2. каждый класс находится путем замены "_" в имени класса на "/" и добавления ".php" в конце файла class = My_App_Smart_Object = packages/My/App/Smart/Object.php

Преимущества этого подхода (используемого практически любым фреймворком) также заключаются в более разумной организации вашего кода:-)

 1
Author: andy.gurin, 2008-09-25 21:41:50

Поиск файлов повсюду замедлит работу (намного больше попаданий на диск). Загрузка всех ваших классов на случай, если они вам понадобятся, потребует больше памяти. Указание того, какие классы вам нужны в каждом файле, трудно поддерживать (т. Е. Они не удаляются, если они больше не используются).

Реальный вопрос в том, что из этого для вас важнее? В конце концов, все это компромиссы, так что вам придется выбрать один. Однако можно утверждать, что большая часть накладных расходов во втором и третьем вариантах речь идет о фактической компиляции кода. Использование чего-то вроде APC может значительно снизить накладные расходы на загрузку и компиляцию каждого класса при каждой загрузке страницы.

Учитывая использование APC, я бы, скорее всего, разделил свой код на модули (например, модуль веб-интерфейса, модуль взаимодействия с базой данных и т.д.) и попросил бы каждый из этих модулей импортировать все классы для своего модуля, а также классы из других модулей, которые им могут понадобиться. Это компромисс между двумя последними, и я обнаружил, что он работает достаточно хорошо для моих нужд.

 0
Author: Dan Udey, 2008-09-25 19:25:11

Я склонен использовать простой подход, при котором __autoload() консультируется с именами классов сопоставления хэша с относительными путями, которые содержатся в файле, который восстанавливается с помощью простого скрипта, который сам выполняет рекурсивный поиск.

Для этого требуется, чтобы скрипт запускался при добавлении нового файла класса или реструктуризации базы кода, но он также позволяет избежать "хитрости" в __autoload(), которая может привести к ненужным вызовам stat(), и это имеет то преимущество, что я могу легко перемещать файлы в рамках моей базы кода, зная, что все, что мне нужно сделать, это запустить один скрипт для обновления автозагрузчика.

Сам скрипт рекурсивно проверяет мой каталог includes/ и предполагает, что любой PHP-файл, не указанный в коротком списке исключений (сам загрузчик плюс некоторые другие стандартные файлы, которые у меня обычно есть), содержит класс с тем же именем.

 0
Author: Rob, 2008-09-25 22:00:00

Подход Zend Framework заключается в том, чтобы выполнять автоматическую загрузку на основе стандарта папки PEAR (class_foo сопоставляется с /Class/Foo.php), однако вместо использования заданного базового пути он использует include_path.

Проблема с их подходом заключается в том, что невозможно заранее проверить, существует ли файл, поэтому автоматическая загрузка попытается включить файл, которого нет ни в одном из путей include_path, с ошибкой, и никогда не даст другим функциям автоматической загрузки, зарегистрированным в spl_autoload_register, возможность включить файл.

Таким образом, небольшое отклонение заключается в том, чтобы вручную предоставить массив базовых путей, в которых автоматическая загрузка может ожидать найти классы, настроенные в стиле PEAR, и просто выполнить цикл по базовым путям:

<?php
//...
foreach( $paths as $path )
{
    if( file_exists($path . $classNameToFilePath) )
        include $path . $classNameToFilePath;
}
//...
?>

Конечно, вы будете вроде как искать, но для каждой загрузки вы будете выполнять только в худшем случае n поисков, где n - количество базовых путей, которые вы проверяете.

Но если вам все еще приходится рекурсивно сканировать каталоги, вопрос не в том, "Повредит ли автоматическая загрузка моему производительность", вопрос должен звучать так: "почему я разбрасываю файлы своих классов в случайной структуре?" Придерживаясь структуры PEAR, вы избавите себя от многих головных болей, и даже если вы решите выполнить включение вручную, в отличие от автоматической загрузки, не будет никаких догадок о том, где находятся файлы классов, когда вы выполняете инструкции include.

 0
Author: dcousineau, 2008-09-25 23:49:01