Контакти

Прискорення PHP програм. Оптимізація PHP – головна ознака професійного коду eAccelerator: прискорення повторного завантаження PHP-коду

При розробці великих проектів поступово постає питання про оптимізацію коду проекту: наскільки виправдано витрати пам'яті, як можна збільшити швидкість виконання написаного php-коду. Спочатку багато хто не замислюється про правильність та ефективність написаного коду, пишуть за принципом: працює - та й добре. Незважаючи на те, що інтерпретатор PHP досить швидко виконує php-код, і є безліч вузьких місць, що уповільнюють швидкість виконання коду, що знаходяться поза PHP, оптимізація php-коду також займає важливе місце, і оптимізацію коду необхідно застосовувати вже на початку процесу написання коду .

Більшість сценаріїв PHP виконують прості дії. Стандартна поведінка сценарію - завантаження невеликої кількості інформації від користувача, отримання деякої інформації з бази даних або файлу, виведення відповідного HTML та надсилання результату роботи клієнту. Тут, перш за все потрібно зрозуміти, що саме має стати результатом оптимізації: швидкодія, зручність масштабування, зменшення кількості ресурсів сервера, що використовуються, зменшення часу передачі даних або всі разом. В останньому випадку необхідно не тільки знайти всі критичні ділянки, але й збалансувати їх оптимізацію.

Наведу найпростіший приклад, нехай на сервері, що має 100 Мб вільної оперативної пам'яті, є два скрипти, результат роботи яких однаковий. Перший скрипт оптимізований на максимальну швидкодію, вимагає 10 Мб пам'яті та отримує дані з файлу шляхом повного його прочитання, другий - на мінімальну витрату пам'яті, вимагає 5 Мб пам'яті та отримує дані з того ж файлу частинами. В результаті одного запиту перший скрипт виконається швидше другого, але якщо буде більше десяти запитів одночасно, саме швидкість роботи другого скрипта стане вищою. Чому так відбувається? У першому скрипті вузьким місцем є використання ресурсів пам'яті, у другому – особливості системи введення-виведення. Після витрати першим скриптом всієї доступної оперативної пам'яті система перейде до використання віртуальної пам'яті, при цьому додатковим вузьким місцем цієї схеми стане та ж система введення-виведення.

Звичайно, цей приклад дуже спрощений, і окрім оперативної пам'яті існують й інші вузькі місця, але головна думка така: оптимізація для одного випадку може стати критичним місцем в іншому. У прикладі, в результаті оптимізації для незначного збільшення швидкості при низьких навантаженнях, суттєво зменшилася швидкість виконання скрипту за більш високих. Тому, щоб отримати вищу віддачу, важливо витрачати свої сили на оптимізацію областей, які дійсно заслуговують на увагу.

Я не розглядатиму тут оптимізацію операційної системи, оптимізація налаштувань сервера тощо, т.к. більшість веб-майстрів користується хостингом і, відповідно, не зможе самостійно все налаштувати. Тут буде розглянуто лише оптимізацію php-коду. Слід зазначити, що в кожному конкретному випадку деякі види оптимізації будуть корисні, інші - будуть марною тратою часу і сил. Часто корисність удосконалення коду буде дуже мала. Можливо, згодом, внутрішні зміни в PHP зроблять успішну оптимізацію марною або навіть шкідливою.

Нижче наведено основні дії щодо підвищення продуктивності для PHP 5 версії:

Дії оптимізації витрати оперативної пам'яті:

  1. Аналіз результатів роботи функцій. Перед написанням функції перевірте, чи немає стандартного аналога.
  2. Звільнення пам'яті у разі закінчення використання великих масивів або об'єктів лише у глобальній області видимості (у локальній області видимості пам'ять буде звільнено автоматично). Зверніть увагу, що функція unset()видаляє змінну в області видимості і, лише у разі відсутності на об'єкт інших посилань, звільняє пам'ять, що займає об'єкт. Присвоєння змінної значення nullзавжди знищує об'єкт і звільняє пам'ять, яку він займає, незалежно від того, чи є ще посилання на цей об'єкт. У цьому змінна нічого очікувати видалена з області видимості, тобто. фактично змінна міститиме невизначене (нульове) значення і, відповідно, займатиме пам'ять зміст цієї змінної (порядку 72 байт).
  3. Аналіз виправданості використання ООП (об'єктно-орієнтованого програмування). Перед написанням об'єктно-орієнтованого коду, задайте собі два питання: «Чи потрібен тут об'єктно-орієнтований підхід?» і «чи можу писати об'єктно-орієнтований код?». Наприклад, визначення статичної функції всередині класу збільшує обсяг пам'яті, необхідної лише змісту цієї функції, на 10-18%. Використання як структура масиву, а не класу, також дозволяє заощадити пам'ять. Можливо, буде вигідніше просто винести функції в окремий файл, а не реалізовувати їх як методи класу.
  4. Аналіз можливості реалізації статичної версії методу у класі. Якщо метод не використовує параметр $this, то він має бути оголошений з використанням ключового слова static.

Дії зі збільшення швидкості виконання коду:

  1. Аналіз оптимізованості SQL-запитів. У більшості проектів саме оптимізація SQL-запитів дає найбільше збільшення продуктивності.
  2. Використання буферизації виводу, всіляких модулів, що кешують, дозволяє збільшити продуктивність на 25%-100%.
  3. Використання більш коротких імен для змінних, функцій, констант та класів може підвищити продуктивність до 20%. У той же час не забувайте про подальшу підтримку коду, ім'я функції набагато зручніше при модифікаціях коду.
  4. Перевірка існування змінної (функція isset()) перед зверненням до неї. Придушення помилки, що виникає при зверненні до неіснуючої змінної шляхом використання @ сильно знижує продуктивність.
  5. Використання " одинарних лапок " дозволяє інтерпретувати код швидше, т.к. у разі "подвійних лапок" усередині рядка ведеться пошук змінних
  6. Аналіз можливості винесення «зайвих» функцій із циклу. Наприклад, заміна функції count()на змінну, обчислену до початку циклу і що містить результат цієї функцій, у виразі for($i=0; $i підвищить продуктивність цього циклу. В іншому випадку функція count()буде викликатися та виконуватися на кожній ітерації циклу.
  7. Використання оператора caseзамість множинного використання конструкції if...else.
  8. Використання явного звернення до полів масиву. Звернення виду $array["id"]виконується у 7 разів швидше, ніж звернення $array. Крім того, це захищає від помилок за подальшої підтримки скрипта, т.к. одного прекрасного дня може з'явитися константа з ім'ям id.
  9. Використання додаткової змінної, що містить посилання на кінцевий масив при обробці багатовимірних масивів у циклі. Для прискорення циклу for($i = 0; $i< 5; $i++) $a["b"]["c"][$i] = func($i); , до початку циклу можна записати наступну інструкцію $item =p$a["b"]["c"]і переписати цикл так: for($i = 0; $i< 5; $i++) $ref[$i] = $i; .
  10. Використання модулів Apache mod_gzip та mod_deflate дозволяє скоротити трафік, за рахунок чого збільшиться швидкість завантаження сторінок.

Наступні дії щодо оптимізації коду підвищують швидкодію лише у разі багаторазового використання:

  1. Використання ++$iзамість $i++у циклах дає приріст продуктивності 6%.
  2. Використання "подвійних лапок" для конкатенації (склеювання) змінних. Інструкція виду $s="$s1$s2$s3"інтерпретується швидше, ніж $s=$s1.$s2.$s3. Це твердження справедливе лише трьох і більше змінних.
  3. Використання повних шляхів в інструкціях includeі requireдозволить витрачати менше часу на пошук системою реального шляху.
  4. Закриття відкритих коннектів до бази даних після того, як потреба в них відпадає. У той же час не слід багато разів підключатися до однієї бази даних.
  5. Аналіз можливості заміни include()і include_once()на require()і require_once()відповідно.
  6. Використання HTML-вставок у код, замість виведення значного обсягу статичних рядків (що не містять результатів роботи коду). Взагалі, швидкість видачі статичної сторінки (HTML) у кілька разів швидше видачі сторінки написаної на PHP. Але не варто захоплюватися, т.к. введення інтерпретатора в режим обробки PHP і виведення з нього також навантажують сервер.
  7. Аналіз можливості заміни функцій preg_replaceі str_replaceв деяких випадках. Функція str_replaceпрацює швидше, ніж preg_replace, і в той же час функція strtrшвидше функції str_replace. Також, використання рядкових функцій strncasecmp, strpbrkі striposбільш оптимально, ніж використання регулярних виразів. Однак замість вкладеності цих функцій слід використовувати саме функції регулярних виразів.
  8. Використання явної ініціалізації змінних. Наприклад, інкремент неініціалізірованної змінної в 9-10 разів повільніше, ніж попередньо ініціалізованої. Крім того, при явній ініціалізації змінних виникає менше помилок.
  9. Як висновок хотілося б відзначити, що використання конструкції echoзамість функції printне дає відчутного зростання продуктивності.
  • Для визначення часу початку виконання скрипту, замість функцій, що повертають поточний час, краще використання $_SERVER["REQUEST_TIME"].
  • Використовуйте профайлер, щоб визначити критичні ділянки коду.

Перед оптимізацією швидкодії коду я настійно рекомендую перевірити оптимізацію SQL-запитів до бази даних, а також оптимізувати http-запити, зменшити розмір js і css, подумати над кешуванням шаблонів, і тільки після цього зайнятися перевіркою коду на продуктивність.

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

Існує ряд правил, яких варто дотримуватись, щоб збільшити швидкість роботи додатків на PHP. Правила прості та не вимагатимуть значних змін у існуючих додатках.

Fastcgi

FastCGI - це один із варіантів підключення PHP до Web серверу. Найкраще використовувати у зв'язці з Nginx. PHP-fpm (Fastcgi контейнер для PHP) і Nginx за замовчуванням підтримують спільну роботу і дуже легко налаштовуються.

OpCache


Як зазвичай виконується PHP скрипт? PHP відкриває файл із кодом, компілює його, потім виконує. Оскільки файлів може бути багато, процес їх відкриття, читання та компіляції може забирати купу ресурсів. Якщо файли не змінюються, то постійну компіляцію можна робити. Найкраще зробити її один раз і закешувати результат.

Саме це робить модуль opCache. Результат першої компіляції буде збережено в кеш, з яким і працюватиме PHP. Таким чином, це прискорить виконання за рахунок відсутності важкого процесу компіляції. Коли файли зміняться, модуль скине кеш і забезпечить перекомпіляцію. Коротше, цей модуль робить дуже корисну економію ресурсів. І це без потреби його налаштовувати.

У версії PHP5.5+ цей модуль поставляється у стандартному складанні. У попередніх версіях модуль необхідно встановлювати самостійно. Перевірити наявність можна так: php-i | grep opcache

# Порожній висновок означатиме, що модуля немає

Якщо версія надто рання, краще використовувати APC: apt-cache search php-apc

# Це альтернатива opCache, але робить те саме

Кешування

Часто код просто повільний. Наприклад:

  • звернення до зовнішніх API
  • важкі вибірки з баз даних
  • обробка великих файлів
session.save_handler = memcache session.save_path = "tcp:// localhost:11211"

# localhost:11211 це стандартний хост та порт Memcache

Крім цього, така схема зберігання дозволить масштабуватись на кілька серверів.

Оптимізація коду

ООП

Пам'ятайте! ООП – це завжди повільно. Об'єкти потрібно створювати, десь зберігати та знищувати. Не використовуйте об'єкти, якщо вони не потрібні. Наприклад, тут:

set_title($_GET["title"]); $post->set_description($_GET["description"]); $post->save();

# $posts = список об'єктів Post, отриманих якимось чином foreach ($posts as $post) ( echo $post->title . "
"; }

# Використовуємо список об'єктів тільки для того, щоб вивести властивість

У цих прикладах використання ООП немає особливого сенсу. Натомість витрачає ресурси. Намагайтеся використовувати масиви, коли об'єкти не потрібні:

$_GET["title"], "description" => $_GET["description"]]);

# Уникнули створення об'єкта, функція просто зберігає дані з масиву в базу

"; }

# Набагато краще — зробити просту вибірку та вивести потрібні дані з масиву

Дрібниці

Під час роботи з файлами використовуйте абсолютні шляхи. Тоді не будуть відбуватися зайві операції пошуку файлу:

include "/var/www/file.php"; file_get_contents("/var/www/dir/data.txt");

Константи класів працюють ефективніше, ніж define:

class posts (const PER_PAGE = 10; ...)

Не використовуйте функції за умови for, т.к. вони повторюватимуться на кожній ітерації циклу:

$max = mysql::get_col("SELECT count(*) FROM posts"); for ($i = 0; $i< $max; $i++) { ... }

Як ключі масивів завжди вказуйте рядки з лапками:

$post["title"] = "Перший пост";

Використовуйте вбудовані функції роботи з рядками замість регулярних виразів, якщо це можливо.

strpos($post["title"], "добре");

Використовуйте рядки з одинарними лапками:

$post["title"] = "У цьому випадку немає додаткової обробки змінних"

PHP cron-скрипти

Коли PHP використовується для розробки скрипту, який буде виконуватися по крону, слід уникати використання глобальних змінних. Наприклад:

(.+?)<\/title/", $rss, $matches); }

(.+?)<\/title/", $rss); if ($has_something) $updates= time(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates= time(); )

Тепер змінна $updates зростатиме до максимальної межі. Коли буде досягнуто ліміту пам'яті, скрипт буде зупинено. Встежити за змінними досить важко, тому краще використовувати функції. Усі змінні, створені всередині функції будуть видалятися після завершення:

process(); function process() ( $rss = file_get_contents("http://somesite.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); }

Найважливіше

  • Обов'язково використовуйте opCache для PHP. Це безкоштовнозаощаджує ресурси.
  • Використовуйте FastCGI (найкраще Nginx + PHP-fpm).
  • Функції у крон завдання допоможуть уникнути витоків пам'яті.
  • Кешування повільних ділянок коду часто є найпростішим рішенням для прискорення роботи.
  • Пам'ятайте про

Продуктивність рішень на PHP — найчастіша тема різних суперечок та дискусій. Ми не будемо зараз брати участь у них. Адже як би там не було, все залежить від конкретного завдання. Наприклад, мені відомий достовірний випадок, коли програмний код протягом півтора року переписували на Асемблері. Спочатку він був написаний на Сі. Коли роботи завершилися, позаду залишилися сотні робочих днів великої групи розробників, а на руках — версія програмного забезпечення, повністю написана на Асемблері. Яке ж було здивування команди, коли в результаті їх витвір на Ассемблері заробило набагато повільніше їхнього ж, більш раннього творіння на Сі!

Оптимізація програмного коду – завдання багатогранне. Слід враховувати багато чинників. Слід розуміти, що в ряді випадків нею взагалі можна знехтувати: зрештою, часто простіше докупити високопродуктивного заліза, ніж оплачувати додаткову роботу команди висококласних розробників. Автоматизація, індустріалізація, друже мої! Роботи замінюють людей. Адже колись були такі професії, як, наприклад, професія ліхтарника чи ліфтера, ні, не того, який зараз лагодить та обслуговує ліфти. Того, який раніше був штурманом ліфта та возив пасажирів, куди вони просили. Нині це вже здається смішним. А років через енну кількість сміх викликатимуть пілоти літаків. Ті літатимуть на повністю автоматизованих системах управління тощо.

Так чи інакше, немає сенсу оптимізувати дуже прості або рідко використовувані частини програмного забезпечення. Принаймні доти, поки все інше не в повному порядку. А на що саме слід звернути увагу насамперед? Зараз ми про це говоритимемо.

Розглянемо з прикладу PHP. Насправді, що б там не говорили про нього, PHP нітрохи не гірший за Perl або ASP.NET, я б сказав навіть навпаки — у PHP значно більше переваг. Чому ж йому найчастіше дістається? Дуже просто тому, що він найпопулярніший! Адже і Windows лають усі, під неї найбільше вірусів, у ній найбільше знайдених «дір». Але стоїть на її популярність ... Хм більше 98% користувачів працюють саме під Windows. На решту разом узятих операційних систем припадає не більше 2% користувачів. Не дивно, що до Windows така увага. Я впевнений, що якщо будь-яка інша ОС була б настільки ж популярна (і настільки ж складна, функціональна і доступна), в ній було б знайдено не менше дір. Ну та гаразд, це розмова для окремої теми.

Повертаючись до PHP, крім усього іншого, це, мабуть, найпростіша мова програмування, що широко використовується для Інтернету. Його простота і доступність обумовлюють армію новачків, які хоч щось у ньому намагаються робити. Їхня некомпетентність часто стає причиною негативних дискусій про PHP. Той самий ASP.NET не настільки доступний. Як наслідок – основні його «носії» – досить грамотні люди. З усіма наслідками. Але доступність PHP жодним чином не нівелює його переваг в руках професіоналів.

Зрештою, на чому написано найпопулярнішу соціальну мережу, і другий за відвідуваністю веб-ресурс у світі, facebook? А його аналог vkontakte? Звісно ж, на PHP!

Слід розуміти сферу застосування. Якщо вам потрібно проводити серйозні обчислення, особливо пов'язані з мультимедіа, з великими даними та високими навантаженнями, наприклад, обробкою відео онлайн, звичайно ж, краще написати відповідний код на тому ж Сі та вже використовувати його під PHP як відкомпільований модуль. PHP - це швидше якийсь універсальний шаблонизатор, ніж мова програмування, якою ми його розуміємо. У PHP завдання зовсім інші.

У зв'язку з цим, в оптимізації продуктивності PHP коду та підходи інші: тут важливіше оптимізація самого алгоритму, моделі розв'язання задачі, ніж саме коду. Хоча є й винятки.

7 принципів або 7 позицій оптимізації коду PHP.

1) Любов до готових бібліотек.

Різні готові бібліотеки – речі, безумовно, корисні та зручні. Але слід не забувати, що безкоштовний сир буває тільки в мишоловці. За все так чи інакше, а платити доводиться.

Розробка програмного забезпечення для реалізації задуму якогось сайту завжди (за умови співвідносних рівнів виконавців, звичайно ж) у плані продуктивності буде значно вигідніша, ніж застосування готової, універсальної CMS (Content Management System – система управління вмістом, «движок» сайту). Низька продуктивність – розплата за універсальність CMS. Це те саме, що їздити на базар на особистому автобусі, або навіть, на літаку, але не на своєму легковому автомобілі. Те саме і з готовими бібліотеками.

Але чому я поставив бібліотеки на перше місце? Тому що, якщо вони застосовуються, то відразу з'їдають левову частку продуктивності. Дивіться самі: підключення одних тільки Smartyі DbSimpleвідразу ж "з'їдає" близько 0.025 сек. часу та майже 3/4 Мб ОЗУ. І це на непоганому сервері за низького загального навантаження. Додати сюди ще якийсь phpMailer, і ми маємо 0,03 сек. витраченого часу та 1 Мб зжерленої пам'яті просто на порожньому місці. Ми ще нічого не робили, лише підключили модулі, це ще навіть без їхньої ініціалізації! У мене є один самописний проект, на кшталт соціальної мережі, так у ньому на повне створення сторінки в середньому йде відчутно менше ресурсів. Інший приклад - движок новинного сайту, який я розробляв: публікації, коментарі тощо. За великим рахунком, нічого надскладного, але й гідна швидкість — в середньому менше 0.001 сек. на генерацію сторінки та до 0.15 Мб пам'яті. Проекти побудовані на зв'язці PHP+MySQL. До речі, таким чином, другий із них, спокійно тримає понад 400тис. хітів на добу, з сплесками до 1600 хітів за хвилину в списах і майже 500 хостами онлайн. На VPS за $30/міс. А підключи до нього ті три бібліотеки, тоді вже не обійтися без виділеного сервера, і не найслабшої конфігурації. Адже справа нерідко доходить до застосування з десятка готових бібліотек.

З іншого боку, безумовно, якщо ви розробляєте невеликий сайт — для фірми, або особисту сторінку, піклуватися про оптимізацію, і, таким чином, відмовлятися від застосування готових бібліотек немає сенсу. Час дорожчий. Якщо відвідуваність вашого сайту не більше ніж 1000 відвідувачів на добу, не варто витрачати час на ідеальний і швидкий код. Використовуйте готові бібліотеки. Вам вистачить ресурсів будь-якого віртуального хостингу. Якщо у вас відвідуваність досягає 2-3 тис. відвідувачів на добу, вже є сенс задуматися про оптимізацію коду. Але все ж таки слід добре подумати над тим, чи варто вам на даному етапі відмовлятися від готових бібліотек і вбивати час на переробку коду (або час і гроші на програміста, який це зробить). Найчастіше простіше просто купити додаткові ресурси, або перейти на VPS, оплачуючи по $10-50 на місяць.

З іншого боку, слід зважати на складність переходу на рішення без застосування готових бібліотек. Той же движок новинного сайту я написав майже за один день. Адже до того ж, «важкі» скрипти не тільки вимагають більш потужного хостингу, але й уповільнюють відкриття сторінок сайту в браузері, особливо якщо сторінка формується протягом декількох секунд. Якщо вам не дуже накладно відмовитись від застосування готових бібліотек — я б радив робити це у будь-якому випадку.

Підводячи підсумки, ще раз наголошу — ви можете спокійно застосовувати бібліотеки, нарощуючи потужність серверів, але не слід забувати, що це перша причина повільної роботи ваших скриптів, і крім високого навантаження на «залізо», вони є причиною багатьох затримок завантаження сторінок сайту.

2) Ігнорування Zend Optimizer, eAccelerator

Ці чудові модулі в основному займаються оптимізацією та динамічним кешуванням відкомпілюваного PHP коду ( байт - коду). Часто дозволяють підняти продуктивність майже в десятки разів. Їх застосування має сенс насамперед на досить великих і високовідвідуваних проектах, хоча ви можете оптимізувати і будь-які інші сайти на PHP — це не вимагатиме від вас по суті ніяких додаткових маніпуляцій. Про застосування даних модулів ми ще поговоримо наступного разу, це досить об'ємна тема. Поки вам достатньо запам'ятати цей пункт.

3) «Криве» застосування баз даних

По суті, це окрема тема. Вам слід пам'ятати, що кожне підключення до бази даних, кожен запит, кожна зайва таблиця в запиті і т.д. - Все це створює відчутне навантаження. Але все ж таки, логіка самої БД, а не інтерфейсу роботи з нею, несе найбільше навантаження. Мені нещодавно доводилося оптимізувати один дуже популярний модуль для одного з найпопулярніших «рухів» форуму. Як мені відразу вдалося з'ясувати — цей модуль і був головною причиною суттєвих гальм. Додавши одну невелику таблицю та два нових SQL запити до PHP коду, продуктивність форуму була підвищена на 60-80% (залежно від сторінки), споживання пам'яті знизилося на 5-7%! І це все практично на рівному місці. Як бачите, це той випадок, коли додавання «зайвої» таблиці та «зайвих» запитів істотно збільшує продуктивність. Я пішов не екстенсивним, а інтенсивним шляхом, покращивши логіку. І отримавши справді чудовий результат.

На тему оптимізації БД ми поговоримо найближчим часом. Зараз торкнуся лише аспект, пов'язаний з інтерфейсом роботи, як на PHP, так, втім, і будь-якою іншою мовою програмування.

Отже, перш за все завжди використовуйте файли замість БД, якщо в цьому є сенс. Коли у цьому є змил? Припустимо, ви пишете движок сайту новин. Новина додається туди раз і назавжди. Вона не схильна до наступних змін, вона велика і цілісна. Набагато простіше та ефективніше помістити її в окремий файл, а не у БД. А ось рецензію до новини вже краще в БД. Адже на певних сторінках вам явно доведеться виводити список останніх рецензій на тему, або список випадкових рецензій. Якщо писати кожну рецензію в окремий файл — при виведенні, скажімо, 50 рецензій на сторінці, нам доведеться підключати до роботи стільки ж відповідних файлів рецензій. Писати всі рецензії в той самий файл теж не дуже добре: при їх великій кількості файл буде дуже великим, і тільки розростатися з часом, продуктивність, відповідно, знижуватися. Та й це може бути досить незручною і небезпечною справою — робота з такими файлами. Інша справа «закидати» наші невеликі рецензії в БД та «висмикнути» потрібні одним нескладним запитом. Те саме стосується будь-яких часто редагованих даних. Наприклад, писати лічильник переглядів новин на файлах – велика дурість. Лише БД.

Що стосується з'єднання з БД, його варто закривати як тільки в ньому відпадає потреба. Однак, не варто цього робити, якщо в роботі даного скрипта воно ще знадобиться.

Слідкуйте за вмістом змінних, яким надаються результати виконання запитів. Є сенс використовувати unsetу ситуаціях, коли серйозні обсяги даних не потрібні.

4) Відсутність кешування

У низці випадків кешування просто незамінне. Розглянемо найпростіший приклад. Трохи вище, коли йшлося про БД, я наводив приклад зі списком рецензій. Припустимо, ми заходимо на якусь сторінку, де відображається список із 50 рецензій до останніх новин. Як правило, їх можна вибрати з БД одним нескладним запитом. Але з іншого боку, ми можемо заздалегідь створити файл, який міститиме всі ці 50 рецензій у готовому вигляді. Нам не потрібно буде вибирати їх із БД, форматувати згідно з нашим шаблоном і вставляти в потрібне місце на сторінці. Ми просто відразу підключаємо все це із сформованого заздалегідь файлу.

Суть кешування зводиться до створення кешу з найчастіше використовуваних і рідко змінюваних даних. Наприклад, як часто вам доведеться оновлювати кеш ваших 50 рецензій? Зрозуміло, що кожного разу, коли додаватимуться нові новини, щоб наш кеш відображав актуальну інформацію. А як часто додаватимуться нові новини? Припустимо, кожні 15 хвилин, тобто. до 100 разів на добу. А яка відвідуваність цього сайту, як часто переглядають ці рецензії? На проекті, «движок» якого я розробляв, близько 70 тис. разів на добу. Таким чином, замість того, щоб виконувати вибірку з бази, форматування та вставку цих рецензій по 70 тис. разів на добу, вона зазвичай виконується не більше 100 разів, решта — лише прості інклуди повністю готових даних.

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

Не забувайте про те, що кеш не обов'язково зберігати лише у файлах і в ньому не обов'язково можна зберігати лише частини нашої майбутньої HTML-сторінки. А особливо якщо він схильний до частих, систематичних оновлень. Наприклад, список даних про користувачів, що знаходяться онлайн, набагато розумніше тримати в БД, таблиці типу Memory.

5) Буфер, стиснення, фронтенд http-сервер

Все дуже просто. У процесі виконання всі дані, які виводяться користувачеві, відразу йому й відправляються. Грубо кажучи, доки дані не будуть забрані, продовження виконання коду не виконується. Так що якщо в процесі роботи ваш скрипт відправляє готовий HTML - код через функцію echo, наприклад, або будь-яким іншим методом, то крипт передає дані "по шматочках", щоразу "підвисаючи". Набагато грамотніше виводити дані в буфер приблизно так:

php //ініціалізуємо буферизацію
ob_start (); //Виконання коду скрипту
//... //завершуємо буферизацію, вилучаємо дані
$html = ob_get_contents ();
ob_end_clean ();
exit( $html ); ?>

Увімкнення динамічного стиснення готових HTML - сторінок (

ob_start(`ob_gzhandler`);

) може стиснути їх у середньому на 20-60%, збільшуючи швидкість завантаження та знижуючи кількість «висять» процесів. У вас обмеження щодо трафіку на хостингу? Тоді динамічний стиск сторінок принесе подвійну вигоду.

Звичайно, слід враховувати, що буферизація дещо підвищує споживання пам'яті, а стиснення навантаження на процесор. Але ці жертви найчастіше з лишком окупаються приростом швидкості. Причому як швидкістю створення, а й швидкістю завантаження сторінки.

На завершення, фронтенд http-сервер може вивести продуктивність ваших PHP скриптів на новий рівень. Справа в тому, що навіть з кешуванням, процеси, пов'язані із запитом користувача, «висітимуть» до того, поки користувач не прийме всі дані (або поки не вийде ліміт відведеного на це часу). Суть фронтенд сервера в тому, щоб відразу ж приймати дані, дозволяючи відразу вивантажувати процеси, що відпрацювали. Він є якоюсь сполучною ланкою між користувачем і досить «важким» сервером бекенд — де виконуються ваші PHP скрипти. Але завдяки своїй «легкості», фронтенд сервер суттєво знижує споживані ресурси. Знову ж таки, це дуже велика тема і ми розглядатимемо її більш детально, у найближчому майбутньому.

6) Тотальний іклуд

Припустимо, ви створили свій «движок» на PHP, дотримувалися всіх попередніх порад. У ньому практично неминуче буде безліч різних інклудів: файлів конфігурації, функцій, мов і т.д. Суть зводиться до того, що навіть звичайний іклуд того ж файлу з функціями вимагатиме чимало часу і пам'яті, навіть якщо крім функцій в інклуді немає виконуваного коду, і не одна з функцій не викликається.

Але ж функції бувають найрізноманітніші та найспецифічніші. Отже, поміщати весь список функцій в один файл, і щоразу підключати його — не найкращий вихід. Наприклад, на сайті є реєстрація користувачів: для цього у вас може бути низка спеціальних функцій, які використовуються лише при реєстрації. То навіщо виносити їх у загальний інклуд функцій, який підключатиметься при кожному зверненні до сторінок сайту?

Не нехтуйте оптимізацією інклудів. Виносите те, що застосовується не повсюдно окремі, спеціалізовані інклуди. Ще один приклад для закріплення. Мій улюблений движок новинного сайту. Функції додавання новин, коментарів, їх контролю та пре-парсингу займає близько 1/3 коду загальної кількості функцій. Але як часто вони потрібні? В 1 із 100 запитах? Або в 1 із 200? Або ще рідше? То навіщо ж їх щоразу вантажити? Це справді може суттєво знизити продуктивність ваших рішень.

7) Зайва функціолізація та ООП-тимізм

Функції необхідно застосовувати лише тоді, коли це справді має сенс. Давайте пригадаємо базову мету функцій. Це не що інше, як винос

часто використовуються в межах одного циклу роботи програми

частин коду окрему, загальну часть. У принципі, виносити код в «окрему частину» має сенс і тоді, коли він виконується за деякою відносно малоймовірною подією. Наприклад, прикріплення фото до поста на форумі. Винесення обробника завантаження та обробки картинки в «окрему частину» позитивно позначиться на продуктивності, навіть якщо він укладений в умову (факт завантаження картинки). При цьому якщо дана «окрема частина» нам знадобиться лише один раз, краще виконати її просто як код (інклуд), а не як функцію. Функції завжди потребують деяких додаткових ресурсів. Те саме стосується і ООП-програмування в PHP. ООП-код споживає більше ресурсів, тому якщо вам не принципово ООП-форматування коду, краще відмовитися від нього. Я говорю саме про ООП-форматування, оскільки ООП-підхід у PHP має мало спільного із самим поняттям ООП-програмування. Як і PHP з класичним розумінням мов програмування та їх завдань – про що я писав на початку.

Ось ви ознайомилися з 7 основними принципами продуктивного коду на PHP. Це тільки — лише початок. Попереду ми ще багато цікавого, більш конкретного матеріалу з цієї теми.

Одним з основних критеріїв успішності будь-якого інтернет-ресурсу є швидкість його роботи і з кожним роком користувачі стають все більш вимогливими за цим критерієм. Оптимізація роботи php-скіптів – це один із методів забезпечення швидкості роботи системи.

У цій статті я хотів би представити на суд громадськості свою збірку порад та фактів щодо оптимізації скриптів. Збірка збиралася мною досить довго, заснована на кількох джерелах та особистих експериментах.

Чому збірка порад та фактів, а не жорстких правил? Тому що, як я переконався, немає «абсолютно правильної оптимізації». Багато прийомів і правил суперечливі і виконати їх неможливо. Доводиться вибирати сукупність методів, якими прийнятно користуватися без шкоди безпеці та зручності. Я зайняв рекомендаційну позицію і тому в мене поради та факти, яких Ви можете дотримуватися, а можете і не дотримуватися.

Що б не було плутанини, я розділив усі поради та факти на 3 групи:

  • Оптимізація на рівні логіки та організації додатку
  • Оптимізація коду
  • Марна оптимізація

Групи виділені умовно і деякі пункти можна зарахувати відразу до кількох із них. Цифри наведені для середнього сервера (LAMP). У статті не розглядаються питання пов'язані з ефективністю різних сторонніх технологій та фреймворків, оскільки це тема окремих дискусій.

Оптимізація на рівні логіки та організації додатку

Багато порад і фактів, що належать до цієї групи оптимізації, є дуже значущими і дають дуже великий виграш у часі.

  • Постійно профілюйте свій код на сервері (xdebug) та на клієнті (firebug), щоб виявити вузькі місця коду
    Слід зазначити, що профільувати треба і серверну, і клієнтську частину, оскільки не всі помилки сервера можна виявити на самому сервері.
  • Кількість, що використовуються в програмі функцій користувача, ніяк не впливає на швидкість
    Це дозволяє використовувати в програмі незліченну кількість функцій користувача.
  • Активно використовуйте функції користувача
    Позитивний ефект досягається рахунок того, що всередині функцій операції ведуться тільки з локальними змінними. Ефект цього більше, ніж витрати на виклики функцій користувача.
  • «Критично важкі» функції бажано реалізувати сторонньою мовою програмування у вигляді розширення PHP
    Це вимагає навичок програмування сторонньою мовою, що значно збільшує час розробки, але в той же час дозволяє використовувати прийоми поза PHP.
  • Обробка статичного файлу html швидше, ніж файлу php, що інтерпретується.
    Відмінність часу на клієнті може становити близько 1 секунди, тому має сенс чіткий поділ статики і сторінок, що генеруються засобами PHP.
  • Розмір файлу, що обробляється (підключається) впливає на швидкість
    Приблизно на обробку кожні 2 Кб витрачається 0.001 секунди. Цей факт штовхає нас на проведення мінімізації коду скриптів під час перенесення на робочий сервер.
  • Намагайтеся не використовувати постійно require_once або include_once
    Ці функції потрібно використовувати за можливості повторного зчитування файлу, в інших випадках бажано використовувати require і include .
  • При розгалуженні алгоритму, якщо є конструкції, які можуть опрацьовуватися і їх обсяг порядку 4 Кб і більше, то оптимально їх підключати за допомогою include.
  • Бажано використовувати перевірку даних, що відправляються на клієнта
    Це викликано тим, що під час перевірки даних за клієнта, різко знижується кількість запитів з неправильними даними. Системи перевірки даних клієнта будуються в основному з використанням JS і жорстких елементів форми (select).
  • Бажано великі конструкції DOM для масивів даних будувати на клієнті
    Це дуже ефективний метод оптимізації під час роботи з відображенням великого обсягу даних. Суть його зводиться до такого: на сервері готується масив даних і передається клієнту, а побудова конструкцій DOM надається JS функцій. В результаті навантаження частково перерозподіляється із сервера на клієнт.
  • Системи, побудовані на технології AJAX, значно швидше, ніж системи, що не використовують цю технологію
    Це викликано зменшенням обсягів виведення та перерозподілом навантаження на клієнта. На практиці швидкість систем з AJAX у 2-3 рази вища. Примітка: AJAX створює ряд обмежень на використання інших методів оптимізації, наприклад, робота з буфером.
  • При отриманні post-запиту завжди повертайте щось, можна навіть пропуск
    Інакше клієнту буде відправлено сторінку помилки, яка важить кілька кілобайт. Ця помилка часто зустрічається в системах, що використовують технологію AJAX.
  • Отримання даних із файлу швидше, ніж із БД
    Це багато в чому викликано витратами підключення до БД. На мій подив, величезний відсоток програмістів маніакально зберігають усі дані в БД, навіть коли використання файлів швидше та зручніше. Примітка:у файлах можна зберігати дані, за якими не ведеться пошук, інакше слід використовувати БД.
  • Не здійснюйте підключення до БД без необхідності
    З невідомої мені причини багато програмістів здійснюють підключення до БД на етапі зчитування налаштувань, хоча далі вони можуть не робити запитів до БД. Це шкідлива звичка, яка коштує в середньому 0002 секунди.
  • Використовуйте постійне з'єднання з БД за малої кількості одночасно активних клієнтів
    Вигода у часі спричинена відсутністю витрат на підключення до БД. Різниця у часі приблизно 0.002 секунди. Примітка:при велику кількість користувачів постійні з'єднання використовувати небажано. При роботі з постійними з'єднаннями має бути механізм завершення з'єднань.
  • Використання складних запитів до БД швидше, ніж використання кількох простих
    Різниця в часі залежить від багатьох факторів (обсяг даних, налаштування БД та ін.) та вимірюється тисячними, а іноді навіть сотими, секунди.
  • Використання обчислень на стороні СУБД швидше, ніж обчислення на стороні PHP для даних, що зберігаються в БД
    Це викликано тим фактором, що для таких обчислень на стороні PHP потрібно два запити до БД (отримання та зміна даних). Різниця в часі залежить від багатьох факторів (обсяг даних, налаштування БД та ін) і вимірюється тисячними та сотими секунди.
  • Якщо дані вибірки з БД рідко змінюються і до цих даних звертається безліч користувачів, має сенс зберегти дані вибірки у файл
    Наприклад, можна використовувати наступний простий підхід: отримуємо дані вибірки з БД і зберігаємо їх як серіалізований масив у файл, далі будь-який користувач використовує дані з файлу. Насправді такий метод оптимізації може дати багаторазовий приріст швидкості виконання скрипта. Примітка:При використанні даного методу потрібно писати інструменти для формування та зміни даних файлу, що зберігається.
  • Кешуйте дані, які рідко змінюються, за допомогою memcached
    Виграш часу може бути дуже значним. Примітка:кешування ефективне для статичних даних, для динамічних даних ефект знижується і може бути негативним.
  • Робота без об'єктів (без ОВП) швидше, ніж робота з використанням об'єктів, приблизно втричі
    Пам'яті «з'їдається» також більше. На жаль, інтерпретатор PHP не може працювати з ОВП також швидко як із звичайними функціями.
  • Чим більша мірність масивів, тим повільніше вони працюють
    Втрата часу виникає через обробку вкладеності структур.

Оптимізація коду

Дані поради та факти дають незначні порівняно з попередньою групою приріст швидкості, але у своїй сукупності ці прийоми можуть дати непоганий виграш часу.

  • echo та print значно швидше, ніж printf
    Різниця в часі може сягати кількох тисячних секунди. Це викликано тим, що printf служить для виведення форматованих даних і інтерпретатор повністю перевіряє рядок на входження таких даних. printf використовується лише для виведення даних, яким потрібне форматування.
  • echo $var."text" швидше, ніж echo "$var text"
    Це викликано тим, що двигун PHP у другому випадку змушений шукати змінні всередині рядки. Для великих об'ємів даних та старих версій PHP відмінності за часом помітні.
  • echo "a" швидше, ніж echo "a" для рядків без змінних
    Це викликано тим, що у другому випадку двигун PHP намагається знайти змінні. Для більших обсягів даних розбіжності у часі досить помітні.
  • echo "a","b" швидше, ніж echo "a"."b"
    Виведення даних через кому швидше, ніж через точку. Це пов'язано з тим, що у другому випадку відбувається конкатенація рядків. Для більших обсягів даних розбіжності у часі досить помітні. Примітка:це працює тільки з функцією echo, яка може приймати кілька рядків як аргументи.
  • $return="a"; $return.="b"; echo $return; швидше, ніж echo "a"; echo "b";
    Причина в тому, що виведення даних потребує деяких додаткових операцій. Для більших обсягів даних розбіжності у часі досить помітні.
  • ob_start(); echo "a"; echo "b"; ob_end_flush(); швидше, ніж $return="a"; $return.="b"; echo $return;
    Це зумовлено тим, що вся робота здійснюється без звернення до змінних. Для більших обсягів даних розбіжності у часі досить помітні. Примітка:цей прийом неефективний, якщо ви працюєте з AJAX, тому що в цьому випадку дані бажано повертати у вигляді одного рядка.
  • Використовуйте «професійну вставку» або? a b
    Статичні дані (поза програмним кодом) обробляються швидше, ніж виведення даних PHP. Цей прийом називається професійною вставкою. Для більших обсягів даних розбіжності у часі досить помітні.
  • readfile швидше, ніж file_get_contents , file_get_contents швидше, ніж require , а require швидше, ніж include для виведення статичного контенту з окремого файлу
    За часом зчитування порожнього файлу коливання від 0.001 до readfile до 0.002 для include .
  • require швидше, ніж include для файлів, що інтерпретуються
    Примітка:при розгалуженні алгоритму, коли є можливість не використовувати файл, що інтерпретується, треба використовувати include , т.к. require підключає файл завжди.
  • if (...) (...) else if (...) () швидше, ніж switch
    Час залежить від кількості гілок.
  • if (...) (...) else if (...) () швидше, ніж if (...) (...); if (...) ();
    Час залежить від кількості гілок та умов. Необхідно використовувати else if скрізь, де це можливо, оскільки це найшвидша «умовна» конструкція.
  • Найчастіші умови конструкції if (...) (...) else if (...) () треба поміщати на початку розгалуження
    Інтерпритатор переглядає конструкцію зверху вниз, доки знайде виконання умови. Якщо інтерпретатор знаходить виконання умови, то решту конструкції він не переглядає.
  • < x; ++$i) {...} быстрее, чем for($i = 0; $i < sizeOf($array); ++$i) {...}
    Це викликано тим, що у другому випадку операція sizeOf буде виконуватися за кожної ітерації. Час різниці виконання залежить від кількості елементів масиву.
  • x = sizeOf($array); for($i = 0; $i< x; ++$i) {...} быстрее, чем foreach($arr as $value) {...} для не ассоциативных массивов
    Різниця у часі значна і збільшується зі збільшенням масиву.
  • preg _replace швидше, ніж ereg_replace , str_replace швидше, ніж preg_replace , але strtr швидше, ніж str_replace
    Різниця в часі залежить від обсягу даних і може досягати кількох тисяч секунд.
  • Функції роботи з рядками швидше, ніж регулярні вирази
    Це є наслідком попереднього.
  • Видаляйте вже непотрібні змінні масиви для звільнення пам'яті.
  • Намагайтеся не використовувати придушення помилок @
    Пригнічення помилок виробляє ряд дуже повільних операцій, оскільки частота повтору може бути дуже великий, втрати швидкості можуть бути значними.
  • if (isset($str(5))) (...) швидше, ніж if (strlen($str)>4)(...)
    Це викликано тим, що замість функції для роботи зі рядками strlen використовується стандартна операція перевірки isset .
  • 0.5 швидше, ніж 1/2
    Причина в тому, що у другому випадку виконується операція поділу.
  • return швидше, ніж global при поверненні значення змінної функції
    Це викликано тим, що у другий випадок створюється глобальна змінна.
  • $row["id"] швидше, ніж $row
    Перший варіант швидше у 7 разів.
  • $_SERVER[’REQUEST_TIME’] швидше, ніж time() для визначення часу запуску скрипту
  • if ($var===null) (...) швидше, ніж if (is_null($var)) (...)
    Причина в тому, що у першому випадку немає використання функції.
  • ++i швидше, ніж i++ , --i швидше, ніж i--
    Це спричинено особливостями ядра PHP. Різниця за часом менше 0.000001, але якщо у Вас ці процедури повторюються тисячі разів, то придивіться до цієї оптимізації.
  • Інкремент ініціалізованою зміною i = 0; ++i; швидше, ніж ініціалізованої ++i
    Різниця за часом близько 0.000001 секунди, але через можливу частоту повтору слід пам'ятати цей факт.
  • Використання змінних, що «відпрацювали», швидше, ніж оголошення нових
    Або перефразую інакше - Не створюйте зайвих змінних.
  • Робота з локальними змінними швидше, ніж із глобальними, приблизно в 2 рази
    Хоч і різниця в часі менше 0.000001 секунди, але через високу частоту повторення слід намагатися працювати з локальними змінними.
  • Звернення до змінної безпосередньо швидше, ніж виклик функції, всередині якої визначається ця змінна у кілька разів
    На виклик функції витрачається приблизно втричі більше часу, ніж виклик змінної.

Марна оптимізація

Ряд методів оптимізації практично не мають великого впливу швидкість виконання скриптів (виграш часу менше 0.000001 секунди). Незважаючи на це, така оптимізація найчастіше стає предметом суперечок. Я навів ці «непотрібні» факти для того, щоб ви в подальшому не приділяли їм особливої ​​уваги при написанні коду.

  • echo швидше, ніж print
  • include("абсолютний шлях") швидше, ніж include("відносний шлях")
  • sizeOf швидше, ніж count
  • foreach ($arr as $key => $value) (...) швидше, ніж reset ($arr); while (list($key, $value) = each ($arr)) (...) для асоціативних масивів
  • Чи не коментований код швидше, ніж коментований, тому що йде додатковий час на читання файлу
    Дуже безглуздо зменшувати обсяг коментарів для оптимізації, треба просто в робочих («бойових») скриптах проводити мінімізацію.
  • Змінні з короткими назвами швидше, ніж змінні з довгими назвами
    Це викликано скороченням обсягів оброблюваного коду. Аналогічно попередньому пункту треба просто в робочих («бойових») скриптах проводити мінімізацію.
  • Розмітка коду з використанням табуляції швидше, ніж із використанням пробілів
    Аналогічно до попереднього пункту.

Насамкінець хочу раз нагадати, що наведені мною поради та факти не абсолютні і значимість їх застосування залежить від конкретної ситуації. Необхідно пам'ятати, що оптимізація скриптів лише мала частина всієї процедури оптимізації і часто можна спокійно жити без вищеописаних порад.


Якщо у Вас виникли питання, то для якнайшвидшого отримання відповіді рекомендуємо скористатися нашим

  • Як оптимізувати сайт та прискорити його роботу?
  • З якою швидкістю буде і може працювати сайт, відповідно до тих технологій на яких він буде запущений?
  • Які технології слід використовувати налаштування сервера або VPS?

Типова проблема:
В якийсь момент сайт починає відкриватися та працювати надто повільно. Буває, що хостингова компанія блокує сайт за перевищення навантаження чи перевитрату ресурсів. Що ж робити у такій ситуації?

Можливо, сайт став користуватися надто високою відвідуваністю або було встановлено якийсь ресурсомісткий модуль, відбувається атака або сайт заражений вірусом. Так чи інакше, але всі ці випадки мають дещо спільне і це проблема всіх сайтів на всіх хостингах.

І якщо говорити про сервери для PHP, то такою проблемою є спосіб виконання php коду, як і інші значущі налаштування оточення на сервері.
Незалежно від того, чи є проблема у вашому коді чи її немає, висока у вас відвідуваність чи ні, від налаштувань сервера залежить дуже багато. Щоб все сказане не звучало порожніми словами і була написана ця стаття.

У цьому огляді я протестую щойно встановлений сайт на одному з найпоширеніших движків управління контентом Drupal 7.33.

Для тесту вибрано лише одну складову php-хостингу. Ми будемо тестувати web-сервери Nginxі Apache2, модулі mod_phpі php-fpm, версії php php53і php56, подивимося, як оптимізатори впливають apcі opcacheна швидкість роботи сайту


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

Дано:
  • Операційна система Centos 6.7
  • Сервер баз даних: MariaDB 10.21
  • Всі сесії сайтів зберігаються в memcache, щоб прибрати вплив швидкості встановлення сесії на швидкість роботи сайту.
  • На всіх тестах як frontend виступає web-server nginx 1.93. У випадку з Apache2, Nginx виступає як балансувальник, а також для віддачі статики. У конфігураціях без використання Apache2 – безпосереднім web-сервером є Nginx
  • Конфігурація Nginx і MariaDB містять безліч оптимізацій, спрямованих на досягнення максимальної продуктивності, але для всіх учасників тесту ці налаштування однакові і тому їх впливом слід знехтувати
  • Параметри opcache та apc взяті з рекомендацій Bitrix, тому що вони оптимальні та універсальні для більшості сайтів
Як тестуватимемо?

У локальній мережі є сервер zabbix і його завдання щохвилини:

  • Відкривати головну сторінку випробуваного сайту, чекати на певний вміст на сторінці, переконуватися, що відповідь від сервера - код 200.
  • Наступним кроком йде авторизація в адмінку сайту, це відбувається відправкою відповідного запиту POST. Звірка тексту та коду відповіді на сторінці із закладеним еталоном. Цей крок стосується багатьох підсистем web-сервера, і багато в чому його швидкість залежить від швидкості взаємодії з базою даних
  • Останнім кроком є ​​вихід з адмінки сайту, звірка коду відповіді та тексту на сторінці виходу
  • За підсумками кожного кроку, zabbix буде скрупульозно заміряти і записувати швидкість рендерингу php-коду в html зрозумілий браузеру і демонструвати нам графіки отриманих результатів
  • Для кожного випробуваного будуть записуватись значення протягом однієї години і як результат буде виступати середні значення за цю годину
  • Тестування відбуватиметься всередині локальної мережі, тому вплив на результат швидкості інтернет-з'єднання виключено
  • Для зручності сприйняття всі результати показую в порядку зростання. Тобто. найперший результат - це найповільніший. Всі конфігурації були винесені під умовний номер, що дозволить краще орієнтуватися в результатах
  • Верхні графіки - швидкість генерації коду, що вище значення, краще. Нижні графіки - час відповіді сервера і чим нижче значення, тим краще
  • Тестовані сайти живуть своїм життям, у них відбуваються регулярні операції з базами даних та виконуються завдання за розкладом, саме тому крива на графіках може мати злети та падіння

Тестування:

1. Nginx + php-fpm56 без оптимізатора opcache

По архітектурі - це один із найпередовіших варіантів. За продуктивністю – найбільше розчарування.

Продуктивність залишає бажати кращого, але навантаження такий варіант витримуватиме набагато краще, ніж варіант №2 з Apache2. Також такий варіант витрачатиме оперативну пам'ять суттєво ефективніше.

2. Apache2 + mod_php53 без оптимізатора apc

Найбільш типовий для хостингів варіант. 90% популярних хостинг-провайдерів використовують цей варіант. Хоча php53 давно не підтримується розробниками, але в інтернеті дуже багато сайтів, які досі працюють на цій версії.

Такий варіант не тільки дуже повільний, але й швидко падає під невеликим навантаженням через нестачу робочих процесів Apache2, або через нестачу оперативної пам'яті на сервері.

3. Балансування та статика через Nginx, динамічна частина Apache2 + mod_php56 без оптимізатора opcache

Цей варіант створено як рішення для сучасних веб-сайтів. Його пропонують хостинги, які прагнуть надавати свіжу версію PHP. Згідно з існуючою думкою, ця версія PHP повинна бути більш швидкою і безпечною, ніж попередні.

На жаль, далеко не всі сайти можуть працювати повноцінно із цією версією. Майже кожна нова версія PHP перестає підтримувати деякі застарілі та небезпечні функції, порушуючи роботу старого коду.
Сам собою php56 без оптимізатора досить повільний, а mod_php схильний падати і займати всю пам'ять на сервері під навантаженням.

4. Nginx + php-fpm53 без оптимізатора apc

Достатньо передова конфігурація, для тих хто не бажає мати проблеми через помилки з оптимізатором коду. При цьому використовується «сумісна» версія інтерпретатора PHP, а також зі зв'язки забирається ресурсомісткий Apache2.

5. Балансування та статика через Nginx, динамічна частина Apache2 + mod_php53 + apc

Ще одна поширена варіація. Дуже багато хостингів застосовують саме її, при цьому або використовують за умовчанням, або дають можливість включати оптимізатор у своїх панелях управління.
Зазвичай Apache2 залишають для роботи.htaccess-правил, таких як перетворення посилань та ЧПУ.

Отримуємо приріст швидкості у 3,5 рази, порівняно з варіантом без використання оптимізатора.
Сам по собі Apache (при використанні його власного модуля mod_php) витрачає на свою роботу набагато більше ресурсів, ніж варіант з php-fpm. Apache2 схильний падати, якщо в одному з його модулів відбувається збій або заповнювати собою всю оперативну пам'ять сервера.

6. Nginx + php-fpm53 + apc

Відмінний варіант для сайтів на старих двигунах, що не потребують складних.

Саме такий варіант я використовую, коли необхідно підняти застарілий сайт, домогтися від нього задовільної швидкості та надійної роботи при високих навантаженнях.

7. Балансування та статика через Nginx, динамічна частина Apache2 + php-fpm53 + apc

Варіант для застарілих сайтів із складними.htaccess. Наприклад – старі інсталяції Bitrix.

Це ідеальний варіант для застарілих веб-сайтів. Ця конфігурація стійка до високих навантажень, сумісна та досить продуктивна.
Відмінно підходить, коли потрібні правила.htaccess та додаткові модулі Apache2.
З недоліків - застаріла версія php, що не оновлюється, але якщо немає вибору - це найкращий варіант. Відмінно підходить для старої версій Bitrix, Joomla та інших поширених CMS не найсвіжіших версій.

8. Балансування та статика через Nginx, динамічна частина Apache2 + mod_php56 + opcache

Досить продуктивна, але ресурсомістка конфігурація з усіма недоліками mod_php.

Досить швидко, але під навантаженням у сервера може закінчиться пам'ять, а швидкість суттєво впаде.

9. Nginx + php-fpm56 + opcache

Найпродуктивніший варіант.

Це найкращий варіант для всіх сучасних веб-сайтів. Добре тримає навантаження, показує найкращий результат із погляду продуктивності. Саме такий варіант я використовую, коли постає завдання оптимізувати продуктивність сайту та збільшити швидкість його роботи.
Єдиний недолік - це те, що ми не зможемо використати. htaccess і всі правила mod_rewrite потрібно переписати на синтаксис Nginx.
Також не працюватимуть модулі Apache2. Якщо такі використовуються, цей варіант не підійде.

10. Балансування та статика через Nginx, динамічна частина Apache2 + php-fpm56+ opcache

Найкращий варіант для сайтів, де потрібний.htaccess. Ідеально підходить для нових версій Bitrix.

Добре тримає навантаження за рахунок php-fpm. Активно використовую цей варіант для більшості веб-сайтів.

Головна сторінка тестового сайту
Номер конфігурації Архітектура Середній відгук мс.
1 77,04 103,6
2 78,79 103,98
3 78,85 102,38
4 81,55 97,88
5 Apache2 + mod_php53 + apc 303,37 29,36
6. Nginx + php-fpm53 + apc 312,33 24,73
7. Apache2 + php-fpm53 + apc 339,63 23,32
8. 484,96 16,91
9. Nginx + php-fpm56 + opcache 546,34 14,08
10. Apache2 + php-fpm56 + opcache 571,14 13,78
Авторизація в адмінці тестового сайту
Номер конфігурації Архітектура Середня швидкість завантаження кб. Середній відгук мс.
1 Nginx + php-fpm56 без оптимізатора opcache 67,51 239,01
2 Apache2 + mod_php53 без оптимізатора apc 64,61 257,51
3 Apache2 + mod_php56 без оптимізатора opcache 66,75 242,42
4 Nginx + php-fpm53 без оптимізатора apc 68.79 233.15
5 Apache2 + mod_php53 + apc 173,81 94,26
6. Nginx + php-fpm53 + apc 173,3 91,3
7. Apache2 + php-fpm53 + apc 182,1 90,5
8. Apache2 + mod_php56 + opcache 218,35 77,55
9. Nginx + php-fpm56 + opcache 252,83 62,25
10. Apache2 + php-fpm56 + opcache 262,8 60,85
Вихід із адмінки тестового сайту
Номер конфігурації Архітектура Середня швидкість завантаження кб. Середній відгук мс.
1 Nginx + php-fpm56 без оптимізатора opcache 41,01 184,49
2 Apache2 + mod_php53 без оптимізатора apc 42,42 188,97
3 Apache2 + mod_php56 без оптимізатора opcache 42,06 188,37
4 Nginx + php-fpm53 без оптимізатора apc 45,48 169,15
5 Apache2 + mod_php53 + apc 190,1 41,87
6. Nginx + php-fpm53 + apc 185,92 41,24
7. Apache2 + php-fpm53 + apc 202,78 39,21
8. Apache2 + mod_php56 + opcache 315,56 26,23
9. Nginx + php-fpm56 + opcache 373,19 20,43
10. Apache2 + php-fpm56 + opcache 381,21 20,57

Як підсумки:

  • У реальному житті всі варіанти з Apache2 можуть бути повільнішими, так як у своїх тестах я навмисне передав віддачу статики Nginx. Це зроблено, щоб унеможливити вплив швидкості віддачі статики на результати виміру швидкості роботи інтерпретатора PHP. Однією з найбільш слабкою стороною Apache2 і при цьому сильною Nginx є швидкість віддачі статики. Особливо це помітно на високих навантаженнях. Крім того, Nginx менш схильний до атаки «повільних з'єднань»
  • mod_php дуже швидко займає всю доступну пам'ять сервера та втрачає продуктивність на навантаженнях
  • php-fpm витрачає пам'ять значно ефективніше, безпечніше та гнучкіше в налаштуваннях. У ряді випадків він швидший і без високих навантажень.
  • Тест має тонку специфіку, тут ми побачили особливості роботи двигуна Drupal, інші можуть поводитися інакше, але загальна тенденція буде такою ж.

І головне – від конфігурації вашого сервера чи хостингу, залежить швидкість вашого сайту. Підібравши правильну архітектуру, ви можете отримати п'ятикратне збільшення швидкості роботи сайту.

Якщо у вас виникнуть питання, труднощі або потрібна порада:
Мої контакти у



Сподобалася стаття? Поділіться їй