Черные Дыры При Разработке Веб-Проекта

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

.



Черные дыры при разработке веб-проекта



Предисловие.

Недавно мне дали задачу помочь найти проблемы в одном из веб-проектов, созданных, как обычно, на PHP + MySQL, и все это тоже было обернуто в Symfony Framework. База данных начала сильно разрастаться, так как люди собирали события поведения (например, автопарк), которые заливались буквально каждые 5 минут. Естественно, таблица событий разрасталась, и чтобы MySQL как-то с ней справлялся, ее разделили на разделы.

В конечном итоге всё сводилось к различного рода выборкам и отчётам, т. е.

аналитике.

В результате даже простая выборка за период плюс небольшой подсчет заняли 11 секунд и более.

Видимо поэтому было принято решение ограничить выбранный период днями.

И мы пошли:

Задача 1 – База

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

На тестовом примере в 700 тыс.

записей в таблице событий выборка за период увеличилась до 30 секунд .

Вся сложность была в данных.

В таблице событий была запись «события разных типов» со свойством ON или OFF, т.е.

начало и конец определенного события.

Все довольно стандартно, и каждый легко сможет сделать выбор:

  
  
  
   

SELECT ev1.event_point,ev1.event_date, (select event_date from test_events where ev1.event_point = event_point and event_type = (CASE WHEN ev1.event_type = 1 THEN 2 ELSE 1 END) and event_date > ev1.event_date limit 1) as end_date FROM test_events as ev1 WHERE ev1.event_date BETWEEN '2012-1-1' AND '2012-1-31' AND ev1.event_type IN (1 , 2)

Для примера и теста использовался один тип событий: 1 начало и 2 окончания, хотя пар в базе около 40. В результате, просто выбирая записи за период, добавляя сразу конец этого события, убирает из MySQL порядок 20-30 сек.

.

Для сравнения также была взята бесплатная база данных SQL Server 2008 в редакции Web, все это запускалось на MS Server 2008 R2 в виртуальной среде VirtualBox. Скажу сразу, Веб-редакция хоть и бесплатна, но не имеет ряда важных опций, особенно важных для аналитики, например, нет оптимизации и кеширования Вида и Процедуры.

Все тесты показали, что MS SQL легко выполняет запрос менее чем за 1 сек в 1КК данные.

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

Это несложно вычислить на уровне SQL-сервера; накладываем сверху условие и получаем готовый отчет:

SELECT event_point,SUM(TIMESTAMPDIFF(HOUR,event_date,end_date)) FROM ( SELECT ev1.event_point,ev1.event_date, (select event_date from test_events where ev1.event_point = event_point and event_type = (CASE WHEN ev1.event_type = 1 THEN 2 ELSE 1 END) and event_id > ev1.event_id limit 1) as end_date FROM test_events as ev1 WHERE ev1.event_date BETWEEN '2012-1-1' AND '2012-1-31' AND ev1.event_type IN (1 , 2) ) report GROUP BY event_point

Вот пример той же базы данных MS SQL, который запускается мгновенно, менее чем за 1 секунду.

А вот с MySQL можно не дождаться результата, увеличив срок, база данных ляжет намертво.

Видимо те, кто собирал проект, это поняли и решили сосредоточиться на обработке выделения непосредственно на PHP. И чтобы не терять 20-30 секунд на JOIN, было решено сделать простой SELECT за период, закинуть все в Array и потом быстро найти начало и конец и потом легко распечатать суммы.

Что и было сделано, в итоге я снова зашёл в тупик, рост периода стал занимать до 1 минуты.

для расчета.

И я начал изучать вторую проблему, пытаясь понять, почему просто пробежка по массиву занимает так много времени.

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

Вот вторая проблема.



Проблема 2 — Массив в PHP

Изучив все данные, я понял, что PHP не может быстро обрабатывать большие массивы.

Почитав на различных форумах, увидел обсуждения, подтверждающие эту версию.

Это проблема PHP. Было решено написать простой тест для проверки фактов.



<Эphp $summary[] = array(); $count = 5000; for($i1=0;$i1<$count;++$i1){ $summary[$i1] = $i1; } $t = microtime(true); for($i1=0;$i1<$count;++$i1){ for($i2=0;$i2<$count;++$i2){ if("5468735354987"!="654654655465"){ $summary[$i1] = $i1*$i2; } } } echo "<li>time: ".

(microtime(true)-$t).

' ms</li>'; $sum = 0; for($i1=0;$i1<$count;++$i1){ $sum = $sum + $summary[$i1]; } echo "<li>test["+$sum+"]"; ?>

Код был создан на основе задачи в проекте.

В этом тесте перебиралось 5000*5000 = 25КК петель, а для увеличения скорости даже использовался ++$i вместо $i++.

В результате этот тест дал 11 секунд .

Попытка запустить этот код прямо в консоли без веб-сервера дала мне 10 секунд .

И все это запускалось у меня на компьютере, а не на хосте или виртуальной машине, и все с конфигурацией: Intel Core i5, 8 ГБ.

PHP 5.3.9 Понимая, что для PHP это предел того, что можно выжать, я решил протестировать этот код на других платформах, имея под рукой виртуальную машину с MS Server 2008 R2. Тестовый код легко перенесся на ASP, ASPX, WSC, VBS и NodeJS. В результате я получил следующие данные:

Черные дыры при разработке веб-проекта

На скриншоте мы видим три варианта теста.

1) виртуальная машина 2) мой компьютер 3) доступные мне серверы в Интернете.

1. PHP на удивление выдал очень похожие результаты, учитывая, что все запускалось на совершенно разных ресурсах и мощностях.

2. ASP, близкий аналог PHP, показал худшие результаты, и это тоже зависит от мощности окружения.

3. WCS очень разочаровал, учитывая, что Microsoft в свое время описала его как скомпилированную версию ASP, которая должна работать гораздо быстрее, что оказалось совершенно неверно.

4. VBS — чисто консольный вариант скрипта, хоть и показал лучшие результаты, чем PHP, но для веб-проекта неприемлем.

5. ASPX показал просто отличные результаты.

Я не удивлен, ведь это C#.

6. NodeJS также показал, как и ожидалось, просто отличные результаты.

Вот все варианты скрипта: test.php

<Эphp $summary[] = array(); $count = 5000; for($i1=0;$i1<$count;++$i1){

Теги: #php #MySQL #JavaScript #benchmark #разработка веб-сайтов #php #JavaScript

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.