Úvod
Téměř každý, kdo vytváří větší webové aplikace, pravděpodobně používá nějaký z aktuálně dostupných frameworků. Jedním z hlavních parametrů při jeho výběru je samozřejmě vkus daného jedince (skupiny) a zkušenosti v určitém programovacím jazyce. Ale co když se najde programátor, který chce vytvořit aplikaci a neví, jaký framework použít? Nejspíš se nebude učit s každým a následně si vybere ten, který mu vyhovuje nejvíce, ale pokusí se na internetu najít testy a srovnání, aby si zvolil dle jeho aktuálních potřeb. Hlavním parametrem při tomto hledání by byl nejspíše výkon, rychlost a paměťová náročnost. Protože patřím přesně do této skupiny a nepodařilo se mi najít požadovaný aktuální srovnávací test, rozhodl jsem se, že jeden takový vytvořím. Dle průzkumů a různých názorů dostupných na internetu, jsem vybral 14 nejznámějších PHP frameworků (jejich přehled najdete na konci tohoto článku) a pokusil se je porovnat na základě jejich rychlosti a náročnosti při komunikaci s databází.
Každý framework je alespoň trochu odlišný, ať už se jedná o použité programovací jazyky nebo strukturu uspořádání zdrojových souborů. Hlavním aspektem jejich rozdílnosti je ale množství dostupných funkcí a knihoven a případná rozšiřitelnost. Jestliže aplikace používá knihovny, které nepotřebuje přímo k běhu dané aplikace, tak to může mít negativní dopad na její rychlost.
Většina dostupných testů se zabývá pouze vypsáním věty „Hello world“ nebo jednoho jednoduchého SQL příkazu, z tohoto důvodu bylo použito spíše zátěžové testování a různé příkazy.
Konfigurace testu
Test jsem prováděl na dvou vlastních počítačích, a to tak, že na jednom běžel lokální server a na druhém program pro testování. Tuto konfiguraci jsem zvolil, aby test nebyl ovlivněn výkyvy připojení nebo rozdílným zatížením použitého hostingu a aby testovací program neovlivňoval výkon počítače se serverem.
K testování byly použity:
Stolní počítač se serverem:
- Procesor: Intel(R) Core(TM)2 Duo E8400, 3.00 GHz
- Paměť: 8.0 GB DDR2
- HDD: 5400 RMP, SATA
- OS: Ubuntu Server verze: 12.04.1 LTS x86
- Apache HTTP server ve verzi 2.2.22
- MySQL klient ve verzi 5.5.24
- PHP 5.3.10
Notebook s testovacím programem:
- Typ: ASUS UL80VT
- Procesor: Genuine Intel(R) CPU U7300, 1.3GHz
- Paměť: 4.0 GB DDR3
- HDD: 5400 RMP, SATA
- OS: Microsoft Windows 7 Professional x64, Service Pack 1
Další nástroje:
- Wi-Fi router: TP-LINK TL-WR340GD
- Testovací program: Apache JMeter 2.8 (r1393162)
- Databáze Sakila
Průběh testu
Jak bylo zmíněno výše, test byl prováděn na dvou počítačích. Nejprve jsem nainstaloval a nakonfiguroval Ubuntu server s Apache a MySQL na stolním počítači. Následně jsem nainstaloval databázi Sakila a poté jsem postupně vytvářel jednotlivé projekty (aplikace) tak, aby se vzájemně neovlivňovaly.
Každá aplikace měla za úkol:
- Vypsat seznam všech zákazníků (tabulka customer)
- Vytvořit nového herce (tabulka actor) s unikátním ID a jménem a příjmením dle požadavku
- Zkontrolovat existenci záznamu a následně editovat vytvořeného herce vybraného dle ID
- Zkontrolovat existenci záznamu a následně smazat vytvořeného herce vybraného dle ID
Pro každou funkci byla vytvořena samostatná stránka obsahující funkcionalitu určenou výhradně pro zpracování daného požadavku.
Nastavení programu Apache JMeter
K testování jsem využil testovací program Apache JMeter, který byl pro každý projekt nastaven tak aby generoval 30 uživatelů s ramp-up periodou 10 sekund. Což znamená, že během každé vteřiny se přihlásí 3 noví uživatelé.
Následně byla definována smyčka (loop), ve které každý uživatel prováděl dané úkoly. Počet opakování byl nastaven na 100. V tomto cyklu byly zadávány jednotlivé příkazy přes „HTTP request“, ve kterém byla definována adresa dané stránky a případná data posílaná přes POST příkaz.
Za účelem generování jednoznačných identifikátorů a rozlišení kroků programu, byly vytvořeny dvě počítadla (counter). Počítadlo uživatelů (UserCounter) bylo umístěno před smyčku a počítadlo požadavků (RequestCounter) bylo závislé na daném uživateli a nacházelo se uvnitř daného cyklu. Pro vygenerování ID sloužila matematická funkce „jexl“ využívaná v programu Apache JMeter.
${__jexl(${UserCounter}*1000+${RequestCounter})
Tento vzorec vynásobí pořadí aktuálního uživatele číslem 1000 a přičte k němu hodnotu počítadla cyklů. Například pro 12. uživatele v jeho 54. kroku je vygenerováno ID = 12054.
Pro čtení výsledků daných testů jsem využíval grafy průběhu(Spline Visualizer, Graph Results) a detailnější tabulkové zobrazení zjištěných údajů (Aggregate Report).
Všechny testy byly zaměřeny výhradně na rychlost zpracování jednotlivých požadavků.
Podrobnější průběh testů
1. TEST – Výběr záznamů (SELECT)
Každý uživatel v každém jednotlivém kroku provedl výběr celé tabulky zákazníků a nechal si vypsat informace o každém záznamu (ID, jméno, příjmení).
– Pro jeden každý projekt bylo provedeno 3000 těchto výpisů (100 cyklů pro 30 uživatelů)
2. TEST – Vytvoření nového záznamu (INSERT)
Každý uživatel v každém kroku přidal do databáze záznam o novém herci s unikátním identifikátorem a jménem a příjmením složeným z pořadového čísla uživatele, číslem kroku a označením pro danou buňku.
Př. 12. uživatel ve svém 52. Kroku vložil do tabulky údaje:
- ID: 12052
- First_name: FirstName_U12_R52
- Last_name: LastName_U12_R52
– Pro jeden každý projekt bylo provedeno 3000 těchto vložení (100 cyklů pro 30 uživatelů)
3. TEST – Úprava záznamu (UPDATE)
Každý uživatel zkontroloval dostupnost svých údajů v databázi definovaných aktuálním krokem, a to v závislosti na unikátním ID generovaného dle pořadí uživatele a na aktuálním prováděném kroku.
Údaje následně upravil na formát podobný jako při vkládání, jen s identifikátorem „New“.
Př. 21 uživatel ve svém 87. kroku upravuje údaje v tabulce „Actor“ dle id 21087 na:
- First_name: FirstNameNew_U21_R87
- Last_name: LastNameNew_U21_R87
– Pro jeden každý projekt bylo provedeno 3000 těchto úprav (100 cyklů pro 30 uživatelů)
4. TEST– Smazání záznamu (DELETE)
Každý uživatel zkontroloval dostupnost svých záznamů dle generovaného ID a následně tento záznam smazal.
Př.: uživatel 3 v kroku 10 smazal záznam s ID 3010
– Pro jeden každý projekt bylo provedeno 3000 těchto smazání (100 cyklů pro 30 uživatelů)
5. TEST– Vše zároveň (ALL)
V tomto testu byly provedeny všechny dříve zmíněné kroky s tím rozdílem, že byly všechny prováděny najednou. To znamená, že každý uživatel si v jednom svém kroku nechal vypsat tabulku zákazníků, vytvořil nového herce s unikátním ID jménem a příjmením, tento záznam upravil a na závěr odstranil.
– Pro jeden každý projekt bylo zasláno 12000 požadavků (100 cyklů pro 30 uživatelů a 4 funkce).
Vlastní testování
Testované aplikace jsem vytvářel pomocí 14 nejznámějších frameworků, ve kterých jsem se snažil omezit některé doplňující vlastnosti, aby byly výsledné aplikace co nejvíce podobné. Na závěr jsme přidal i jednoduchou aplikaci napsanou v čistém PHP, která obsahovala pouze funkce určené k nejjednoduššímu zpracování daného požadavku.
Seznam použitých frameworků (abecedně)
- CakePHP 2.2.5, vydán 8. 1. 2013
- CodeIgniter 2.1.3, vydán 8. 10. 2012
- DooPHP 1.4.1, vydán 22. 2. 2011
- Jelix 1.5.0, vydán 20. 2. 2013
- Kohana 3.3.0, vydán 21. 10. 2012
- Laravel 3.2.13, vydán 11. 1. 2013
- Nette 2.0.8, vydán 19. 2. 2013
- Prado 3.2.1, vydán 19. 1. 2013
- Qcodo 0.4.22, vydán 15. 8. 2011
- Recess 0.20, vydán 7. 8. 2009
- Seagull 1.0.4, vydán 14. 1. 2013
- Symfony 2.2.0, vydán 24. 2. 2013
- Yii 1.1.13, vydán 30. 12. 2012
- Zend framework 2.1.4, vydán 13. 3. 2013
Co dál?
Během léta vám postupně předvedeme, jak si jednotlivé frameworky v testu vedly. Projdeme je v abecedním pořadí, každý týden ukážeme dva. Na konci pak vše přehledně shrneme.
Přehled komentářů