Улучшение производительности
============================

Производительность веб-приложения зависит от многих факторов. Главные из них —
обращение к базе данных, файловой системе и пропускная способность сети.
В Yii, для уменьшения падения производительности из-за самого фреймворка, учтён
каждый из этих факторов. Несмотря на это, многие части приложения можно улучшить
для получения более высокой производительности.

Включение расширения APC
------------------------

Включение [расширения PHP APC](http://php.net/manual/en/book.apc.php) —
возможно, самый простой способ улучшить общую производительность приложения.
Расширение оптимизирует и кэширует промежуточный код PHP и выигрывает время,
затрачиваемое на интерпретацию скриптов PHP при каждом запросе.

Отключение режима отладки
-------------------------

Отключение режима отладки — ещё один лёгкий способ увеличить производительность.
Приложение Yii работает в режиме отладки если константа `YII_DEBUG` определена
как true. Режим отладки полезен при разработке, но не лучшим образом влияет на
производительность из-за использования большего числа компонентов. К примеру,
при журналировании ошибок, с каждым сообщением может записываться дополнительная
информация.

Использование `yiilite.php`
---------------------------

Если используется [расширение PHP APC](http://php.net/manual/en/book.apc.php),
мы можем заменить `yii.php` другим загрузчиком — `yiilite.php`. Это даст приложению
ещё больший прирост производительности.

Файл `yiilite.php` поставляется вместе с каждой версией Yii и представляет
собой собранные вместе часто используемые классы. Все комментарии и выражения трассировки
вырезаются, поэтому использование `yiilite.php` уменьшает количество подключаемых файлов
и выполняемого кода.

Стоит заметить, что использование `yiilite.php` без APC может отрицательно
повлиять на производительность, так как `yiilite.php` включает в себя классы,
которые могут не требоваться при каждом запросе и отнимать некоторое время на
парсинг. Также было отмечено, что на некоторых конфигурациях сервера `yiilite.php`
медленнее даже при использовании APC. Лучший способ принятия решения об
использовании `yiilite.php` — провести тесты на прилагающемся демонстрационном
приложении `hello world`.

Использование кэширования
-------------------------

Как уже было описано в разделе «[кэширование](/doc/guide/caching.overview)», Yii
предоставляет несколько решений, которые могут значительно увеличить
производительность приложения. Если генерация каких-либо данных занимает много
времени, мы можем использовать [кэширование данных](/doc/guide/caching.data) для
того, чтобы делать это не так часто. Если часть страницы остаётся неизменной, мы
можем использовать [кэширование фрагментов](/doc/guide/caching.fragment). Если вся
страница не меняется, можно использовать [кэширование страниц](/doc/guide/caching.page).

Если используется [Active Record](/doc/guide/database.ar), можно включить
кэширование структуры базы данных. Это можно сделать, установив в настройках
свойству [CDbConnection::schemaCachingDuration] значение, большее 0.

Кроме описанных настроек приложения можно использовать кэширование на уровне
сервера. Описанное выше
[кэширование APC](/doc/guide/topics.performance#enabling-apc-extension) относится
как раз к ним. Существуют и другие решения, такие как
[Zend Optimizer](http://www.zend.com/en/products/guard/zend-optimizer), [eAccelerator](http://eaccelerator.net/)
и [Squid](http://www.squid-cache.org/).

Оптимизация базы данных
-----------------------

Получение данных из базы часто является узким местом производительности
приложения. Несмотря на то, что кэширование может смягчить потери, оно не решает
проблему полностью. Когда в базе содержатся огромные объёмы данных, и нужно
обновить кэш, получение данных может быть чрезмерно растратным при неверном
составлении схемы данных или запросов.

Будьте осмотрительны при выборе индексов. Их использование может значительно
ускорить `SELECT`-запросы, но замедляет запросы `INSERT`, `UPDATE` и `DELETE`.

Для сложных запросов рекомендуется создать view в базе данных вместо использования
запросов из кода PHP, которые СУБД разбирает каждый раз.

Не злоупотребляйте [Active Record](/doc/guide/database.ar). Хоть [Active
Record](/doc/guide/database.ar) и является удобной проекцией данных в стиле ООП,
но производительность при её использовании, из-за использования объектов для
представления каждой строки результата, падает. Для приложений, интенсивно
работающих с данными, рекомендуется использовать [DAO](/doc/guide/database.dao)
или API для работы с СУБД на ещё более низком уровне.

Последний по счёту, но не по значению совет: используйте `LIMIT` в
`SELECT`-запросах. Так вы сможете избежать получение избыточных данных из базы и
расхода требующейся для их хранения памяти, выделенной PHP.

Минимизация файлов скриптов
---------------------------

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

Для страницы, генерируемой Yii, не исключено, что некоторые скрипты подключаются
компонентами, код которых изменять не хочется (например, компоненты ядра Yii).
Как минимизировать такие скрипты показано далее.

Для начала опишем, какие файлы минимизировать. Зададим свойство
[scriptMap|CClientScript::scriptMap] компонента
[clientScript|CWebApplication::clientScript]. Это можно сделать как в настройках
приложения, так и в коде. К примеру:

~~~
[php]
$cs=Yii::app()->clientScript;
$cs->scriptMap=array(
	'jquery.js'=>'/js/all.js',
	'jquery.ajaxqueue.js'=>'/js/all.js',
	'jquery.metadata.js'=>'/js/all.js',
	…
);
~~~

Приведённый код сделает файлы JavaScript доступными по URL `/js/all.js`.
Если какой-либо из этих файлов требуется для каких-либо компонент, Yii
подключит URL (один раз) вместо того, чтобы подключать отдельные файлы.

Нам понадобится использовать какой-либо инструмент для слияния (и, возможно, сжатия)
JavaScript в один файл и записать результат в `js/all.js`.

То же относится и к файлам CSS.

Увеличить скорость загрузки страницы можно также при помощи
[Google AJAX Libraries API](http://code.google.com/apis/ajaxlibs/). К примеру,
мы можем подключить `jquery.js` с серверов Google вместо того, чтобы использовать
свой сервер. Для того, чтобы это сделать нужно настроить `scriptMap` следующим
образом:

~~~
[php]
$cs=Yii::app()->clientScript;
$cs->scriptMap=array(
	'jquery.js'=>false,
	'jquery.ajaxqueue.js'=>false,
	'jquery.metadata.js'=>false,
	…
);
~~~

Устанавливая значения в false мы запрещаем Yii генерировать код для включения
соответствующих файлов. Вместо этого подключим их с серверов Google:

~~~
[php]
<head>
<?php echo CGoogleApi::init(); ?>

<?php echo CHtml::script(
	CGoogleApi::load('jquery','1.3.2') . "\n" .
	CGoogleApi::load('jquery.ajaxqueue.js') . "\n" .
	CGoogleApi::load('jquery.metadata.js')
); ?>
…
</head>
~~~

Использование символьных ссылок для ресурсов
--------------------------------------------

Если ваш проект интенсивно использует ресурсы, то вы можете увеличить его производительность
посредством [символьных ссылок](http://ru.wikipedia.org/wiki/Символьная_ссылка)
вместо стандартного копирования файлов. Для того, чтобы включить их вам нужно задать
свойство [linkAssets|CAssetManager::linkAssets] компонента приложения `assetManager`
используя конфигурационный файл `protected/config/main.php`:

~~~
[php]
return array(
    // ...
    'components' => array(
        // ...
        'assetManager' => array(
            'linkAssets' => true,
        ),
    ),
);
~~~

Имейте ввиду, что [это потребует дополнительных настроек|CAssetManager::linkAssets].
