1 Востаннє редагувалося VTrim (25.09.2014 16:26:36)

Тема: 40 порад по оптимізації вашого PHP коду

Оригінал статті (авторство): reinholdweber.com
Стаття на російській: http://habrahabr.ru/post/22799/
Переклад на українську: я

1.Якщо метод може бути статичним, оголошуйте його статичним.
2.echo швидше, ніж print.
3.Передавайте в echo декілька параметрів, замість того, щоб використовувати конкатенацію рядків.
4.Встановлюйте максимальну кількість проходів ваших циклів for до циклу, а не під час його виконання.
5.Видаляйте свої змінні для звільнення пам'яті, тим більше, якщо це великі масиви.
6.Остерігайтеся магічних методів, таких як __set(), __get(), __autoload().
7.require_once дорого обходиться.
8.Вказуйте повні шляхи в конструкціях include / require, менше часу буде витрачається на пошук файлу.
9.Якщо вам необхідно визначити час, коли скрипт був запущений, використовуйте $_SERVER['REQUEST_TIME'] замість time().
10.Намагайтеся використовувати strncasecmp(), strpbrk() і stripos() замість регулярних виразів.
11.str_replace() швидше, ніж preg_replace(), але strtr() швидше, ніж str_replace().
12.Якщо функція, як і функції заміни рядків, може приймати в аргументи як масиви, так і одиночні символи, і якщо ваш список аргументів не дуже довгий, подумайте над тим, щоб записати кілька однакових виразів заміни, проходячи один символ за раз, замість одного рядка коду, яка приймає масив як аргумент пошуку і заміни.
13.Краще вибирати затвердження за допомогою конструкції else if, ніж використовувати кілька конструкцій if.
14.Придушення помилок при використанні @ працює дуже повільно.
15.Використовуйте модуль Apache mod_deflate.
16.Закривайте свої з'єднання з БД, коли закінчите працювати з ними.
17.$row['id'] в сім разів швидше, ніж $row[id].
18.Повідомлення про помилки дорого коштують.
19.Не використовуйте функції всередині умови циклу for, наприклад як тут: for($x = 0; $x < count($array); $x). В даному випадку функція count() буде викликатися з кожним проходом циклу.
20.Інкремент локальної змінної в методі - найшвидший. Майже так само працює інкремент локальної змінної у функції.
21.Інкремент глобальної змінної в два рази повільніше, ніж локальної.
22.Інкремент властивості об'єкта (тобто $this->prop++) в три рази повільніше, ніж локальної змінної.
23.Інкремент невизначеної змінної в 9-10 разів повільніше, ніж заздалегідь ініціалізованої.
24.Оголошення глобальної змінної, без використання її у функції, також уповільнює роботу (приблизно на ту ж величину, що і інкремент локальної змінної). Ймовірно, PHP здійснює перевірку на існування змінної.
25.Швидкість виклик методу, судячи з усього, не залежить від кількості методів, визначених в класі. Я додав 10 методів в тестовий клас (до і після тестового методу), без зміни продуктивності.
26.Методи в похідних класах працюють швидше, ніж вони ж, певні в базовому класі.
27.Виклик функції з одним параметром і порожнім тілом функції в середньому дорівнює 7-8 Інкрементам локальної змінної ($localvar++). Виклик схожого методу, зрозуміло, близько 15 інкрементів.
28.Ваші рядки, певні за допомогою ', а не ", будуть інтерпретуватися трохи швидше, т.к. PHP шукає змінні усередині" .. ", але не' ... '. Звичайно, ви можете використовувати це тільки тоді, коли у вашому рядку немає змінних.
29.Рядки, розділені комами, виводяться швидше, ніж рядки, розділені крапкою. Примітка: це працює тільки з функцією echo, яка може приймати кілька рядків в якості аргументів.
30.PHP-скрипти оброблятимуться, як мінімум, в 2-10 разів повільніше, ніж статичні HTML-сторінки. Спробуйте використовувати більше статичних HTML-сторінок і менше скриптів.
31.Ваші PHP-скрипти перекомпілюються кожного разу, якщо скрипти НЕ кешуються. Кешування скриптів зазвичай збільшує продуктивність на 25-100% за рахунок видалення часу на компіляцію.
32.Кешуйте, наскільки це можливо. Використовуйте memcached - це високопродуктивна система кешування об'єктів в пам'яті, яка підвищує швидкість динамічних веб-додатків за рахунок полегшення завантаження БД. Кешированний мікрокод корисний тим, що дозволяє вашому скрипту НЕ компілюватися знову для кожного запиту.
33.При роботі з рядками, коли вам знадобиться переконатися в тому, що рядок певної довжини, ви, зрозуміло, захочете використовувати функцію strlen(). Ця функція працює дуже швидко, адже вона не виконує будь-яких обчислень, а лише повертає вже відому довжину рядка, доступну в zval-структурі (внутрішня структура C, використовувана при роботі із змінними в PHP). Однак тому, що strlen() - функція, вона працюватиме повільно за рахунок виклику деяких операцій, таких як приведення рядка в нижній регістр і пошуку в хеш-таблиці, тільки після яких будуть виконані основні дії функції. У деяких випадках ви зможете прискорити свій код за рахунок використання хитрості з isset().
  Було: if(strlen($foo) < 5) { echo 'Foo is too short'; }
  Стало: if (!isset($foo{5})) {echo 'Foo is too short'; }
  Виклик isset() швидше, ніж strlen() тому, що, на відміну від strlen(), isset() - не функція, а мовна конструкція. За рахунок цього isset() не має практично ніяких накладних витрат на визначення довжини рядка.
34.Інкремент або декремент змінної при допомозі $i++ відбувається трохи повільніше, ніж ++$i. Це особлива специфіка PHP, і не потрібно таким чином модифікувати свій C і Java-код думаючи, що він буде працювати швидше, цього не станеться. ++$i буде швидше в PHP тому, що замість чотирьох команд, як у випадку з $i++, вам знадобиться тільки три. Пост-інкремент зазвичай використовується при створенні тимчасових змінних, які потім збільшуються. У той час, як пре-інкремент збільшує значення оригінальної змінної. Це один із способів оптимізації PHP-коду в байт-код утилітою Zend Optimizer. Тим не менш, це гарна ідея, оскільки не всі байткод-оптимізатори оптимізують це, також залишається чимало скриптів, що працюють без оптимізації в байткод.
35.Не все повинно бути ООП, часто це зайве, оскільки кожен метод і об'єкт займає багато пам'яті.
36.Не визначайте кожну структуру даних як клас, масиви бувають дуже корисні.
37.Не надто розбивайте методи. Думайте, що ви дійсно будете повторно використовувати.
38.Ви завжди можете розбити код на методи пізніше, по необхідності.
39.Використовуйте незліченну кількість наперед визначених функцій.
40.Якщо у вашому коді є функції, які виконуються дуже довго, обдумайте їх написання на C у вигляді розширення.
41.Профіліруйте свій код. Профілізація покаже вам, як багато часу виконуються частини вашого коду.
42.mod_gzip - модуль Apache, який дозволяє стискати ваші дані на льоту і може зменшити обсяг переданих даних до 80%.

Подякували: Replace, koala2

2 Востаннє редагувалося quez (25.09.2014 14:11:24)

Re: 40 порад по оптимізації вашого PHP коду

19.Не використовуйте функції всередині умови циклу for, наприклад як тут: for($x = 0; $x < count($array); $x). В даному випадку функція count() буде викликатися з кожним проходом циклу.

Отак взяли й заборонили викликати функцію в умові циклу, хоч це не завжди неправильно, наприклад: for($x = 0; isEnough(); $x++)

Ну і $x++ швидше всього, у мене подібний код виводив просто дуже багато нулів.

13.Краще вибирати затвердження за допомогою конструкції else if, ніж використовувати кілька конструкцій if.

Знову ж таки, це дві зовсім різні ситуації.

3

Re: 40 порад по оптимізації вашого PHP коду

Питання до автора теми: ви дійсно погоджуєтесь з цими усіма штуками?

6.Остерігайтеся магічних методів, таких як __set(), __get(), __autoload().

що значить остерігайтесь? Можна написати 100 методів а можна 2га (один __set  інший __get ) і все буде добре, а не лапшакод)

7.require_once дорого обходиться.

Цікаво що пропонує автор: include_once ?  )

39.Використовуйте незліченну кількість наперед визначених функцій.

можете пояснити? або переклад поганий або задум)


p.s. попроную код який є у темі брати в тег code ;)

4

Re: 40 порад по оптимізації вашого PHP коду

6. Все ж краще явно задані гетер і сетер, а класи завантажувати явно. Так що погоджуюся з reinholdweber.com . А то потім будете дуже довго шукати, чому це раптом від простого присвоювання щось виводиться перед хедерами, і чому це ваш клас працює зовсім не так, як ви очікували (бо завантажився інший, з іншою літерою, а ваш, явно заданий, тут ні до чого).
7. Я так розумію, тут мова про те, що краще самостійно контролювати, що ви включаєте... хоча не певен. До речі, а де посилання на оригінал? ТС!

5

Re: 40 порад по оптимізації вашого PHP коду

koala написав:

До речі, а де посилання на оригінал? ТС!

Оригіналу вже не існує,є ще стаття на хабрі http://habrahabr.ru/post/22799/ звідки і перекладав.

6

Re: 40 порад по оптимізації вашого PHP коду

VTrim написав:
koala написав:

До речі, а де посилання на оригінал? ТС!

Оригіналу вже не існує,є ще стаття на хабрі http://habrahabr.ru/post/22799/ звідки і перекладав.

Гм... а ви коментарі під тим перекладом читали?
Ну і некоректно писати "переклад з reinholdweber.com", якщо переклад з хабру.

7

Re: 40 порад по оптимізації вашого PHP коду

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

8

Re: 40 порад по оптимізації вашого PHP коду

перевірив пункт 34
З циклом в 500 ітерацій

з ++$i середня швидкість 0,00051 сек
з $i++ середня швидкість 0,00052 сек

9

Re: 40 порад по оптимізації вашого PHP коду

Перевірив пункт 9
З циклом в 500 ітерацій
з $_SERVER[’REQUEST_TIME’] середня швидкість 0,00064 - 0,00065 сек
з time() середня швидкість 0,00067 - 0,00068 сек

10 Востаннє редагувалося VTrim (25.09.2014 19:07:59)

Re: 40 порад по оптимізації вашого PHP коду

Перевірив пункт 19

З функцією перед умовою в циклі 0,00030
З функцією в умові циклу 0,00032 - 0,00033

11

Re: 40 порад по оптимізації вашого PHP коду

VTrim написав:

Перевірив пункт 19

З функцією перед умовою в циклі 0,00032 - 0,00031
З функцією в умові циклу 0,00032 - 0,00033


Невже?

Код
function test1() {
    $arr = array();
    
    for ($i = 0; $i < 1000000; $i++) {
        $arr[] = $i;
    }
    
    $time_start = microtime(true);
    for ($i = 0; $i < count($arr); $i++) {
        $i + $i + $i;
    }
    $time_end = microtime(true);
    return $time_end - $time_start;
}


function test2() {
    $arr = array();
    
    for ($i = 0; $i < 1000000; $i++) {
        $arr[] = $i;
    }
    
    $time_start = microtime(true);
    $len = count($arr);
    for ($i = 0; $i < $len; $i++) {
        $i + $i + $i;
    }
    $time_end = microtime(true);
    return $time_end - $time_start;
}

echo 'Test 1 result: ' . test1() . '. Test 2 result: ' . test2() . '.';

Результат

Test 1 result: 0.15717315673828. Test 2 result: 0.068718910217285.

12 Востаннє редагувалося VTrim (25.09.2014 19:24:23)

Re: 40 порад по оптимізації вашого PHP коду

Replace, ну так я робив самий простий тест,там вже було ясно що без функції в умові код генериться швидше. А чим більше навантаження,тим відрив між двома варіантами більшає. А ще потрібно робити не один замір,тому що кожна нова генерація це зовсім інший час (інколи з великим відривом від попереднього)
Тільки що
Test 1 result: 0.73960590362549
через секунду
Test 1 result: 0.4893810749054

p/s в першому варіанті трохи не те записав,там не 0,00032 - 0,00031,а 0,00030 було

13

Re: 40 порад по оптимізації вашого PHP коду

Ви ж розумієте що є ще і похибки. І різниця в 00001 це фактично в межах похибки і думаю що це не говорить про те хто швидший +±і або і++ Хоча треба робити профайл і бачити всі операції.

Інколи краще написати і±± аніж ++і ;-)

14

Re: 40 порад по оптимізації вашого PHP коду

VTrim, яка різниця з функцією чи без? Замір часу відбувається всередині функції. Можна і окремо запускати. Час не змінититься. Можна спочатку test2, а потім test1. А у вас просто довжина масиву не дуже велика.
Висновок: при дійсно великих об'ємах даних це доцільно робити. Наприклад при роботі з великими масивами даних з БД.

Коли всередині немає операторів
Код
function test1() {
    $arr = array();
    
    for ($i = 0; $i < 1000000; $i++) {
        $arr[] = $i;
    }
    
    $time_start = microtime(true);
    for ($i = 0; $i < count($arr); $i++) {
    }
    $time_end = microtime(true);
    return $time_end - $time_start;
}
 
 
function test2() {
    $arr = array();
    
    for ($i = 0; $i < 1000000; $i++) {
        $arr[] = $i;
    }
    
    $time_start = microtime(true);
    $len = count($arr);
    for ($i = 0; $i < $len; $i++) {
    }
    $time_end = microtime(true);
    return $time_end - $time_start;
}
 
echo 'Test 1: ' . test1() . "\n";

echo 'Test 2: ' . test2();

Результат

Test 1: 0.11841297149658
Test 2: 0.031276941299438

15 Востаннє редагувалося caballero (26.09.2014 00:18:33)

Re: 40 порад по оптимізації вашого PHP коду

При  роботі   з  великими  данними  БД  90% часу  забиратиме  робота  Бд.  Ще  9%  забиратиме передача  данних  по мережі.
    Взагалі - такими  оптимізаціями  займалися   в  часи  MS-DOS.  Зараз  залізо  коштує менше  ніж праця   програміста - дешевше  добавити  проца  або  памяті  та  не  займатися  подібними збоченнями - як  функція  зекономить  мікросекунду.    теоретично  це   може  й  цікаво - практично  немає сенсу..

Подякували: funivan1

16

Re: 40 порад по оптимізації вашого PHP коду

Replace,я говорив,про функцію в умові циклу for (тобто count()),а не про функцію test1 чи test2)

17

Re: 40 порад по оптимізації вашого PHP коду

Погоджуюсь з caballero. Зараз фреймворки саме тому і популярні так як більш-менш реалізують хорошу і прозору логіку роботи. Легше підтримувати ніж макаронний код.

Завжди буде момент коли ми впираємось в залізо. Тобто не завжди є сенс ставити залізо. Деколи варто шукати проблему в своєму коді. АЛЕ. Завжди проблему в коді шукаємо на вищому рівні ажін що швидше echo vs print чи $i++ vs ++$i


;)

Подякували: quez1

18

Re: 40 порад по оптимізації вашого PHP коду

2koala

Все ж краще явно задані гетер і сетер

Можете показати як у вас реалізована робота з базами даних? (можлво код на гітхаб або ще кудись)
Наприклад є таблиця у ній 20 полів. Писати 20 гетерів  + 20 сетерів ?

Оновлено
2VTrim Не потрібно писати декілька постів підряд після себе. Краще оновлюйте попередній.

19

Re: 40 порад по оптимізації вашого PHP коду

funivan написав:

Погоджуюсь з caballero. Зараз фреймворки саме тому і популярні так як більш-менш реалізують хорошу і прозору логіку роботи. Легше підтримувати ніж макаронний код.

Завжди буде момент коли ми впираємось в залізо. Тобто не завжди є сенс ставити залізо. Деколи варто шукати проблему в своєму коді. АЛЕ. Завжди проблему в коді шукаємо на вищому рівні ажін що швидше echo vs print чи $i++ vs ++$i


;)

Що значить на вищому рівні?
Оптимізація починається з малого. Навіть так,з таблиці бд потрібно вибрати тільки нік і ід,а в таблиці допустимо 50 полів,буде грубою помилкою робити SELECT * (вибір всіх) замість SELECT id,nick (того що треба) ,а таке багато хто допускає. Чи наприклад один складний SQL запит буде швидшим декількох простих,бо там функція запиту викликається тільки один раз,а там декілька.

20

Re: 40 порад по оптимізації вашого PHP коду

Взагалі - такими  оптимізаціями  займалися   в  часи  MS-DOS.  Зараз  залізо  коштує менше  ніж праця   програміста - дешевше  добавити  проца  або  памяті  та  не  займатися  подібними збоченнями

за таких як ви програмістів пишуть плеєр якому потрібно 1 гіг оператівки і два ядра проц і це мінімальниі характеристики що б послухати мр3

Подякували: VTrim, koala, bischenko3