Щось давненько ми тут не займалися дурницями.
Сьогодні ми будемо проводити тести з усіма можливими порушеннями їх чистоти і нахабно маніпулювати статистикою.
Питання: як правильно підключати в своєму проекті класи, щоб при цьому заощадити час на їх підключення.
- Старий добрий autoload (). як у всіх нормальних людей.
- Взяти і зібрати всі класи в один файл, як багато вчать.
- Підключати потрібні класи явно через require_once ().
- І новомодна штучка: Phar-архів.
- Phar-архів ще можна робити не простий, а з стисненням (GZ або BZ2).
- Ну і phar'ом також два варіанти: autoload () або пряме підключення вкладених файлів.
- І поверх цього можна акселератором якимось пошаманити.
Інструменти
Інструменти для тестів тут: на гітхабе.
Запуск ./create.php створює каталог test. а в ньому такі речі.
Каталог classes
Структура наших тестованих класів. Все по стандарту PSR-0.
Створюється 5 просторів імен з випадковими іменами. У кожному створюється 5 випадкових класів з випадковим набором методів.
І в кожному з глобальний просторів створюється ще 5 вкладених і в них ще по 5 класів.
Разом 150 класів. Стандартний такий посередній фреймворк.
файл full.php
Весь «фреймворк» одним файлом.
Файл вийшов розміром 85 K. А загальна вага каталогу (за рахунок великої кількості маленьких файлів) 725 К (файлова система ext4).
Кілька сірників вже заощадили.
файл exec.php
Це виконуваний скрипт, в якому викликаються потрібні класи.
Щоб домогтися якоїсь подоби зі звичайними сценаріями: в одному сценарії задіяні не всі класи фреймворка, а тільки 50 (третина). Але до кожного класу може бути кілька звернень.
Робота з кожним класом проста: викликається статичний метод, який виконує найпростіше арифметичне дію. Таким чином час витрачений на роботу з класами не повинно набагато перевершити час витрачений на їх підключення (яке ми і тестуємо).
Phar-архіви
З каталогу classes створюється три phar-архіву: phar-none.phar. phar-gz.phar. phar-bz.phar (без компресії, gz, bz).
Розмір phar-node.phar. 99 К. Більше ніж full.php за рахунок додаткової інформації.
Стислі файли: 51 К (gz) і 61 К (bz). Нормальні то архіватори стискають і трохи краще.
(Потрібно розширення Phar і повинна бути скинута настройка phar.readonly в php.ini)
Файли req.php і phar-req.php
У req.php підключаються всі використовувані в exec.php файли (50 штук).
У phar-req.php теж саме, тільки підключаються вони не з каталогу, а з phar-архіву.
Після створення тестового каталогу запускаємо з консолі тести. /run.php [test].
Аргумент [test] може бути наступним:
autoload. підключення файлів з каталогу за допомогою автолоада.
Автолоад простий: замінює NS1 \ NS2 \ Class на DIR / NS1 / NS2 / Class.php. перевіряє наявність файлу і підключає його.
full. підключення одного великого файлу.
req. підключення потрібних файлів через require_once
phar-auto. підключення з phar через автолоад.
phar-req. підключення потрібних файлів з phar через require_once.
phar-gz і phar-bz. підключення через автолоад зі стислих архівів.
Так як в циклі проганяти такі тести безглуздо, та й взагалі чистотою тестів тут вже і не пахне, просто викликаємо кілька разів з консолі (результати все одно завжди виявляються схожими).
результати
У мене вийшло таке (P. Dual Core 2,8Гц, ubuntu, php 5.5.1):
псевдоаналітиків
Автолоад vs збірка в один файл
Мало того, що збірка в один файл виїла в 3 рази більше пам'яті (підключаємо всі класи, коли потрібна лише третина), так вона ще й за часом програла автолоаду з яким покликана боротися.
Подальші тести показали, що в часі збірка наближається до автолоаду при підключенні близько 50% від загальне числа класів, а потім починає обходити його.
Автолоад vs requre
require очікувано обійшло autoload.
Логічно, адже при автолоаде відбувається багато різних рухів, які закінчуються все тим же require.
Однак, різниця всього лише 10%.
І це при тому, що в тесті require_once для кожного класу викликається тільки один раз (в реальному проекті, якщо перед кожним класом спочатку підключати потрібні йому, один і той же клас буде запитуватися багаторазово і require_once кожен раз буде перевіряти чи підключено вже файл чи ні ).
Крім того, наші тестові файли маленькі. На великому файлі, його підключення і розбір зайняло б набагато більше.
Це до теми оптимізації пошуку класів: можна прибрати з автолоада file_exists (), можна сканувати каталоги і збирати карту класів в масив і використовувати його, ще можна багато чого зробити. Але всі ці оптимізації будуть тільки в межах цих 10%. Просте явне require по швидкості ніяк не оминути.
Phar цілком собі бадьоренько.
Трохи повільніше і трохи більше пам'яті хоче.
Але по споживанню пам'яті до варіанту із збіркою в один файл йому далеко.
Хоча тут теж один файл.
Стиснення: gzip дещо випередив bz2 і тут (вище у нього вийшов менший розмір файлу).
Однак, при стисненні значно знижується швидкість доступу.
Та й ступінь стиснення, як бачили вище, якось не дуже (більш того, при стисненні нормальним архиватором стисненого phar'а результат виходить більше, ніж стиснення нестислого).
Так що використовувати стислі phar'и я б не рекомендував.
Хоча, можливо, який-небудь опкешер вирішив би цю ситуацію.
Zend Opcache
Ну і бажано все це протестувати з усіма опкешерамі, акселераторами і тому подібним.
Але ставити їх все ліниво, так що перевірив тільки на opcache.
При запуску тестів з консолі слід не забути включити в php.ini опцію opcache.enable_cli.
Включення opcahce призвело до двократного падіння споживання пам'яті.
Щодо швидкості точних чисел немає, так як результати почали сильно коливатися, а наші методи не дозволяють усереднити їх по великій кількості тестів.
Однак, коливаються результати приблизно в тих же пропорціях. Максимально: відповідає часу без opcahce, мінімально: в два-три рази менше.
Коли Ви телефонуєте з консолі можуть іноді значно перевершувати за часом виклики через браузер.
1. Нічого паритися через нісенітниці. Оптимізація все одно незначна в порівнянні зі звичайним часом виконання сценарію.
2. autoload () - найкраще і найзручніше рішення. Тим більше всі стандарти типу PSR тепер зав'язані на нього.
3. Проводити збірку декількох файлів в один, побудова карт класів і т.п. можна тільки на продакшені при Деплой.
Коли все більш істотне вже оптимізовано.
При розробці ж: геморою багато, а толку мало.
4. Складання кількох файлів в один дає результат, тільки якщо кожен раз використовується хоча б половина вкладених файлів.
5. phar - добре (для поставляються бібліотек, які не потрібно змінювати).
6. Стиснутий phar - не так добре.
7. Opcahce цілком собі рулить.