Не секрет, что асинхронные запросы к серверу позволяют существенно упростить работы пользователей с сайтом. Так же не является секретом и то, что асинхронные запросы могут поднять производительность работы сайтов. Ведь так велик соблазн загрузить основные стили, js-скрипты, картинки и шрифты и прочее только один раз, а дальше с помощью AJAX подгружать только необходимый контент.

Если вы хотите выжать максимум производительности на сайте используя AJAX, то вам нужна всего лишь одна идея.

Пишите для AJAX индивидуальный код.

Да, вот так, казалось бы чего проще.

Но большинство программистов ленивы (в том числе и я) и не любят писать лишний код. Благодаря этому можно встретить в контроллере (или в неком скрипте) для вывода страницы сайта, новости или статьи блога такую конструкцию:

// подгружаем систему
// получаем необходимый контент

if(isset($_POST['ajax'])) {
  // отправляем необходимый контент в браузер
  // AJAX
  exit();
}
else {
  // вставляем контент в шаблон страницы и показываем ее целиком
  // обычная загрузка страницы
}

Практически все системы, построенные по принципу одной точки входа, так и работают. Из популярных систем к таким можно отнести Drupal, ShopScript (версии с WebAsyst), CodeIgniter и еще много других.

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

<?php
  require_once('includes/application_top.php');

  // дальнейшая обработка данных

По такому принципу работают: osCommerce, DokuWiki, WordPress, Joomla, Bitrix и прочие.

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

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

В таком ключе работают многие системы: PrestaShop, ShopScript, Bitrix и т.д.

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

В моей практике есть один очень показательный пример на Bitrix'е. Хочу сразу оговориться, что это не камень в огород разработчиков Bitrix'а. Кто часто работает с этой системой, знает о ее проблемах и путях обхода этих проблем. И вот об одном из таких путей я расскажу.

Итак, дано:

Есть некий интернет-магазин на Bitrix. В каталоге магазина более 22000 товаров. Товары распределены по более чем 400 категориям. У каждого товара порядка 70 свойств. Для каждого товара есть свой набор поставщиков и информация о остатках на складах этих поставщиков.

Требуется: написать скрипт для формирования YML для яндекса с нетривиальной логикой включения в него товаров. Стандартный модуль Bitrix'а с такой логикой не справляется.

Понятно, что обработать такой массив данных за один присест не возможно и надо бить процесс на итерации. Тут как раз на выручки и приходит AJAX.

Решение 1, стандартное


Пишем модуль для ПА, который отправляет на сервер AJAX запросы на обработку части товаров.
Скрипт на стороне сервере принимает запрос, подключает систему, обрабатывает необходимый блок товаров и формирует часть YML файла. Все очень стандартно.

Все красиво, работает согласно официальной документации. Да вот только на таком объеме данных работает это все порядком 25 минут. Такое время набегает из-за подгрузки системы на каждой итерации (440 итераций по 50 товаров), плюс внутренние издержки выборок из БД.

Решение 2, пишем индивидуальный код для обработки запросов


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

В скрипте на стороне сервера убираем погрузку Bitrix'а и вместо нее подключаем файл конфигурации системы. Используя стандартный PDO напрямую получаем необходимые данные о товарах.

Да, код работает вне основного фреймворка, но зато тот же объем данных обрабатывается за 40 секунд. Это очень показательный пример того, что индивидуальный код для обработки запросов может работает куда быстрее, нежели общепринятые методы реализации.

Я понимаю, что на другой системе и/или другом объеме данных разница в производительности может быть и не существенной. И не факт, что следует жертвовать удобством сопровождения, разводя зоопарк, ради производительности, где она не столь критична. Но если вдруг производительность будет играть решающую роль, то стоит подумать об индивидуальном написании код для обработки AJAX запросов.

Комментарии (10)


  1. DOC_tr
    19.06.2015 16:07
    +4

    я, конечно, не работал с битриксом, но если я все правильно понял ИМ требуется (25 * 60) минут / 440 = 3.4 секунды на то чтобы отобразить 50 товаров?


  1. zxcabs
    19.06.2015 16:20
    +10

    Хотелось бы спросить причем тут ajax?

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


    1. AlexTest
      20.06.2015 07:49
      +1

      Уточню немного. Задача из статьи решается с помощью PHP скрипта, запускаемого на сервере по расписанию — cron task.


    1. OlegZorin Автор
      20.06.2015 21:33
      -1

      Такая задача в кроне висит, заказчик хотел дополнительно запускать ручками.

      Что касается ajax, тут да, если задуматься, то получается, что в данном примере запросы идут не совсем асинхронно. После завершения одного запроса, этим же скриптом запускается другой. И так пока не обработаем все, что есть.

      Возможно пример приведен не совсем в тему, однако, его цель была показать существенное сокращение времени, когда для обработчика запроса пишется свой индивидуальный код.


  1. MetaDone
    19.06.2015 16:28
    +16

    мораль — делаешь что-то на битриксе — не используй его


  1. dshster
    20.06.2015 01:50
    -1

    Ничего не понял, да и не работал с Битриком, но 40 секунд без информирования пользователя о состоянии тоже много. Можно же поступить так: отправить запрос на формирование данных на сервер, сервер тут же вернёт идентификатор запроса и начнёт обработку, с клиента периодически (раз в 5-10 секунд) по этому идентификатору проверять статус обработки и информировать пользователя. когда обработка закончится, в ответ на запрос придёт результат. Кажется это называется REST API.
    Термин AJAX уже давно не употребляется т.к. это давно стандартная технология по-умолчанию в вебе, а статья видимо лежала в закромах лет 10.


    1. Doktor_Gradus
      20.06.2015 12:06

      Такие задачи обычно выполняются регулярно, по крону. Пользователь (вернее, администратор ИМ) вообще информируется только в случае проблем с выполнением задачи. У нас, например, задачи по выгрузке в Яндекс.Маркет и ещё в несколько мест выполняются раз в 1-3 часа (периодичность зависит от задачи). Пользователь задолбается читать, что задача отработала штатно. Наоборот, ему интересно будет сообщение, что задача не выполнилась.

      Никакой аякс, разумеется, не нужен. В Битриксе есть задачи экспорта, можно написать свой скрипт, который будет делать вообще что угодно и повесить его на крон.


    1. OlegZorin Автор
      20.06.2015 21:43

      Сейчас проблема оповещения пользователя о состоянии обработки решается путем возвращения обработанного количества товаров на каждой итерации. В принципе если погнаться за лоском, можно и прогресс бар прикрутить.

      REST в предлагаемой вариации не прокатит. В данном случаи я не могу запустить скрипт, который бы мог крутиться более 30 секунд — time_limit на сервере, администратор которого менять не дал. А искусственно сбрасывать значение времени выполнения на каждой внутренней итерации, через set_time_limit() — не совсем хорошо, на мой взгляд.

      Хотя признаю, что скрипт который работает по крону сбрасывает счетчик времени на каждой итерации.