Оптимізація PHP коду: 7 принципів (исходники), Різне, Програмування, статті

Продуктивність рішень на 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 з класичним розумінням мов програмування та їх завдань – про що я писав на початку.
P.S.
Ось ви і ознайомилися з 7 основними принципами продуктивного коду на PHP. Це тільки – тільки саме початок. Попереду у нас ще багато цікавого, більш конкретного матеріалу по даній темі.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*