Proč Jet používá .php soubory jako úložiště dat a zdroj konfigurace?

Zarazili vás proč jste v adresáři ~/application/config našli soubor db.php a ne třeba db.ini, nebo db.xml? Nebo proč je v adresáři ~/application/data seznam nainstalovaných modulů installed_modules_list.php a ne něco jiného? Má to své technické a především měřitelné a porovnatelné důvody.

Nejlepší bude ukázat si možnosti a různé alternativy například uklání konfigurace a rovnou na nich demonstrovat výhody a nevýhody daného řešení.

Alternativa: .ini soubory

Výhody:

  • PHP obsahuje funkce parse_ini_file a parse_ini_string - není tedy nutné nic extra implementovat za účelem čtení dat.
Nevýhody:
  • I když jsou možnosti .ini souborů opravdu slušné, stále jsou limitované a ne tak flexibilní.
  • PHP má implementované parsování, ale ne vytváření .ini souborů. To by bylo nutné implementovat. Ale to není zas tak zásadní problém.
  • Při nějakém nedopatření a přímém zpřístupnění adresáře konfigurace přes URL jsou .ini soubory snadno přímo čitelné ...

Alternativa: XML

Výhody:

  • Je možné smysluplně uložit vlastně libovolná data.
  • XML je široce podporovaný standard s dobrou podporou v PHP.
Nevýhody:
  • Jak si ukážeme níže, tak je poměrně významná technická režie pro zpracování XML.
  • Při nějakém nedopatření a přímém zpřístupnění adresáře konfigurace přes URL jsou XML soubory snadno přímo čitelné ...

Alternativa: JSON

Výhody:

  • Opět je možné smysluplně uložit vlastně libovolná data.
  • I JSON je dnes široce podporovaný standard s dobrou podporou v PHP.
Nevýhody:
  • I zde si dále předvedeme režii pro zpracování ...
  • Při nějakém nedopatření a přímém zpřístupnění adresáře konfigurace přes URL jsou JSON soubory snadno přímo čitelné ...

Alternativa: serializovaná data pomocí PHP funkce

Výhody:

  • Je možné uložit vlastně libovolná data.
  • Relativně rychlé zpracování.
  • Vše potřebné má PHP v sobě.
Nevýhody:
  • Není to ideální formát pro člověka a je vhodné, aby konfigurace a další data byla pro vývojáře čitelná a také ručně upravitelná.
  • Při nějakém nedopatření a přímém zpřístupnění adresáře konfigurace přes URL jsou soubory snadno přímo čitelné ...

Alternativa: nějaký speciální datový formát (více či méně standardní)

Výhody:

  • ... žádné objektivní výhody
Nevýhody:
  • Nutnost implementace a údržba neužitečného kódu (neobhajitelné náklady - neobhajitelná investice času a peněz).
  • Téměř jistě nepříjemná technická režie.
  • Při nějakém nedopatření a přímém zpřístupnění adresáře konfigurace přes URL jsou soubory snadno přímo čitelné ...

Současné řešení: .php soubory obsahující deklaraci pole

Výhody:

  • Jak si ukážeme v porovnání, tak objektivně technicky nejrychlejší řešení (z několika důvodů).
  • Snadné ukládání a čtení libovolných dat.
  • Pro vývojáře snadno čitelné a modifikovatelné soubory ve formátu, který moc dobře zná - je mu vlastní.
  • Pokud by se díky chybě v nastavení bylo možné dostat do adresáře ~/application/config přes URL, tak se takto jednoduše stejně nic nezobrazí. Je to nesrovnatelně bezpečnější.
  • PHP pracuje se soubory jako s jinými skripty. To znamená, že na ně může (ale nemusí) použít třeba OPCache a je tu možnost mít konfiguraci hezky naparsovanou v paměti. Tím se může doslova škrtnou spousta režijní činnosti při zpracování požadavku.
Nevýhody:
  • .... někomu to může připadat na první pohled málo "punk" a cool :-)
  • Je nutné počítat s případným efektem OPCache (a tuto keš promazávat, pokud je to třeba).

Porovnání

Na základě argumentů se dá předpokládat, že PHP soubory budou nejrychlejší a tedy technicky nejlepší řešení. Teorii je ale nutné ověřit. A výsledek takového ověření si ukážeme.

Nejprve co budeme porovnávat. Ze všech alternativ jsem vybral dva kandidáty - konkurenční technologie, které mohou být brány v úvahu a to: JSON a XML. Důvod? .ini soubory jsou poměrně málo flexibilní (respektive ne tak jak bych si přál), serializovaná data nejsou vhodná pro případný zásah člověkem a speciální datový formát vůbec nezvažuji - není k tomu důvod, když jsou k dispozici funkční a plně dostatečné alternativy.

Metoda porovnání

Je nutné srovnávat srovnatelné a omezit vedlejší vlivy. Tedy vytvořil jsem tři samostatné PHP skripty zcela bez jakéhokoliv frameworku, čistě krátké syrové jednoúčelové skripty.

Každý skript měl provést totéž a to načíst zcela identická data. Respektive identická v tom, že v nich byla vždy stejná informace, ale pokaždé v jiném datovém formátu.

Skripty jsem umístil na můj lokální webserver. Nepoužil jsem žádný sdílený hosting podobně. Postupoval jsem tak, abych měl prostředí plně pod kontrolou a věděl že na daném stroji běží v daný moment právě jen daný test.

Pomocí jednoduchého nástroje Apache Benchmark jsem otestoval výkonnost a propustnost daných skriptů. Vždy za stejných podmínek, aby bylo jasné, které čtení dat aplikaci pod zátěží ovlivní nejvíc.

Načítaná data

Podoba načítaných informací v datech byla při měření zcela identická. Pouze se lišil datový formát jednotlivých souborů:

data.php
return [
    
'connections' => [
        
'default' => [
            
'host' => 'localhost',
            
'port' => 1234,
            
'username' => 'user',
            
'password' => '*********',
        ],
        
'custom' => [
            
'host' => 'somewhere.universe',
            
'port' => 4321,
            
'username' => 'user',
            
'password' => '*********',
        ],
    ]
];

data.json
{
  
"connections": {
    
"default": {
      
"host""localhost",
      
"port"1234,
      
"username""user",
      
"password""*********"
    
},
    
"custom": {
      
"host""somewhere.universe",
      
"port"4321,
      
"username""user",
      
"password""*********"
    
}
  }
}

data.xml
<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <connections>
        <connection>
            <name>default</name>
            <host>localhost</host>
            <port>1234</port>
            <username>user</username>
            <password>*********</password>
        </connection>
        <connection>
            <name>custom</name>
            <host>somewhere.universe</host>
            <port>4321</port>
            <username>user</username>
            <password>*********</password>
        </connection>
    </connections>
</config>

Testovací skripty

Účel testovacích skriptů byl jeden jediný a to přečíst data ze souboru a připravit je do dále zpracovatelné podoby. Nic víc a zcela bez závislosti na čemkoliv.

test_php.php
$data = require 'data.php';

//var_dump($data);

test_json.php
$data file_get_contents'data.json' );

$data json_decode$datatrue );

//var_dump($data);

test_xml.php
$data simplexml_load_file('data.xml');

//var_dump($data);

Průběh měření

Měření proběhlo na laptopu s CPU i7-8550U, 16GiB RAM, SSD, OS: GNU/Linux Ubuntu 20.04.3 LTS, PHP 8.0.14, Apache/2.4.52

Testovací skripty na samostatném virtuálu webserveru Apache. Vše nepotřebné pro test povypínáno, deaktivováno.

Parametry Apache Benchmark: Počet požadavků 100 000. Konkurence: 100.

Podmínky pro všechny testy stejné.

Poměřovaná výstupní hodnota: Počet požadavků za sekundu podle Apache Benchmark. Každý test opakován 3x, porovnávána bude výsledná průměrná hodnota.

Výsledek a závěr

PHP

1. měření 19845.93 rq/s
2. měření 19704.98 rq/s
3. měření 19804.91 rq/s
Výsledný průměr 19785.27 rq/s

JSON
1. měření 16920.07 rq/s
2. měření 16210.12 rq/s
3. měření 16420.59 rq/s
Výsledný průměr 16516,93 rq/s

XML
1. měření 15438.38 rq/s
2. měření 15598.49 rq/s
3. měření 15546.71 rq/s
Výsledný průměr 15527,86 rq/s

Závěr
Na základě objektivních faktů se dá říct, že zvolený způsob ukládání konfigurace a metadat aplikace je nejlepší. Má nejnižší režii (nejméně brzdí aplikaci), je pro vývojáře snadno čitelný a upravitelný, nevyžaduje žádnou speciální implementaci a žádný nadbytečný kód. Daný přístup je rovněž nejbezpečnější. Jako alternativa by připadal v úvahu formát JSON, ale PHP je přece jen o něco rychlejší a bezpečnější.

Předchozí kapitola
Proč?
Další kapitola
Proč Jet nemá žádný šablonovací systém pro view?