Na navigaci | Klávesové zkratky

PHAR - PHP v kompaktním balení

Je tomu právě tři a půl roku, kdy jsem distribuci Texy doplnil o tzv. kompaktní verzi. Zjednodušeně se dá říci, že jde o skript vzniklý spojením všech souborů tvořících knihovnu do jednoho jediného a vynecháním komentářů a nadbytečných mezer. Výsledkem je funkčně identický kód, jen s krapet hustší konzistencí. (Prostě je hustéééj. Jak Salko!)

Záměrem bylo zjednodušit nahrávání knihovny na server – uploadovat desítku malých souborů přes FTP bývá značně pomalejší, než nahrát soubor jeden. Jako vedlejší efekt se ukázalo, že jednosouborová knihovna znatelně zvyšuje výkon aplikace – klidně o 30 %. Používání kompaktních verzí se ujalo a od té doby většina bugreportů hlásila chybu na řádce 1 🙂

S příchodem jmenných prostoru v PHP 5.3 se generování kompaktních verzí poněkud zkomplikovalo – zatím totiž platí, že jeden soubor může obsahovat jen jeden jmenný prostor už to neplatí. To znamená, že „jednosouborová“ verze bude mít přinejmenším tolik souborů, kolik je v knihovně jmenných prostorů, plus případné další soubory řešící problémy se vzájemnou závislostí mezi prostory.

Zároveň však PHP 5.3 přichází s novinkou, která si klade za cíl vnést do kompaktních verzí nový svěží vítr: PHAR – PHP archive. Ostatně myslím, že promluvím za nás všechny, když řeknu: nemusí pršet, hlavně když kape!

Jak takový PHAR balíček vytvořit? Nejprve je nutné v PHP.INI zapnout extension=php_phar.dll a nastavit direktivu phar.readonly = Off. Následující kód zkonvertuje celý Nette Framework do souboru nette.phar

$phar = new Phar('nette.phar');

$phar->buildFromDirectory('libs/Nette'); // enter here path to Nette

$phar->setStub("<?php
Phar::mapPhar('nette.phar');
require 'phar://nette.phar/loader.php';
__HALT_COMPILER();");

$phar->compressFiles(Phar::GZ); // or Phar::BZ2

Nejprve se vytvoří nekomprimovaný archiv ze všech souborů v určeném adresáři a jeho podadresářích – jde o obdobu TAR archivu. Následně se definuje tzv. stub neboli zaváděcí program. Jeho úkolem bude načíst soubor loader.php, který je součástí Nette Frameworku a nalézá se vlastně uvnitř PHAR archivu. Stub musí být ukončen zvoláním __HALT_COMPILER(). Poté je možno archiv zkomprimovat.

Příklad použití:

require 'nette.phar';

echo Html::el('strong')->setText('It works!');

Vypadá to báječně, že? Ovšem podívejme se na věc podrobněji. PHP skripty nejsou v archivu nijak minimalizované, nejsou z nich odstraněny zbytečné komentáře ani mezery. To je potřeba udělat ručně. Takže zatímco komprimovaný nette.phar má nějakých 180 kB, stejný archiv vygenerovaný z kompaktní verze Nette (tj. místo adresáře libs/Nette použijeme libs/Nette.compact) váží pouhých 50 kB. Nicméně pokud si uvědomíme, že

  • minimalizace kódu vede k rychlejšímu parsování (závislost bude dost možná lineární)
  • dekomprimace naopak nutně zpomaluje

dojdeme k závěru, že ideální bude generovat PHAR rovnou z kompaktní verze a ukládat jej nekomprimovaný. Nojo – ale proč teda rovnou nezůstat u kompaktní verze? Bez PHAR režie navíc?

Důvod existuje. Kompaktní verze se vždy načte celá, zatímco PHAR lze parsovat a kompilovat po částech. Takže Zend Framework bude vhodnější zabalit do PHARu, u dibi nebo Texy si můžeme dovolit plný výkon kompaktní verze.

před 16 lety v rubrice PHP | blog píše David Grudl | nahoru

Mohlo by vás zajímat

Komentáře

  1. Martin Malý #1

    avatar

    Nejpozději s uvedeném téhle novinky přijde kdosi s nápadem zPHARovat front controller i všechny další controllery a vytvořit vlastně jeden takový mohutný index.php, který bude obsahovat logiku pro celou aplikaci… bože… takovou novinku unesou programátoři maximálně třikrát za deset let!

    před 16 lety | reagoval [2] David Grudl
  2. David Grudl #2

    avatar
    před 16 lety
  3. kukulich #3

    „…zatím totiž platí, že jeden soubor může obsahovat jen jeden jmenný prostor…“

    To není pravda, i v současné verzi jmenných prostorů bez složených závorek může být v jednom souboru více jmenných prostorů. Původně to opravdu bylo tak, jak je v článku uvedeno, ale kvůli různým frameworkům (myslím, že zmiňovali především Symfony) bylo povoleno více jmenných prostorů v jednom souboru. Ale právě proto se začalo znovu uvažovat o syntaxi se složenými závorkami.

    před 16 lety | reagoval [5] David Grudl
  4. pmg #4

    jde o obdobu TAR archivu

    Mělo by smysl jednotlivé soubory před archivací předkompilovat?

    před 16 lety
  5. David Grudl #5

    avatar

    #3 kukulichu, máš pravdu, v poslední verzi to skutečně jde. Ačkoliv stále nemůže být v jednom souboru kód bez jmenných prostorů a kód s nimi.

    před 16 lety
  6. OndroNR #6

    avatar

    a co autoload? moc sa v tom nevyznam

    před 16 lety
  7. A. #7

    avatar

    Vypadá to zajímavě, už se těším, až si do PHARu zabalím ZF. Díky 🙂

    před 16 lety
  8. Jan Tvrdík #8

    avatar

    Jaká by byla rychlost např. Texy!, kdyby se „zkomprimovali“ jednotlivé soubory zvlášť a nebalily se všechny dohromady? Pokud jsou totiž sbaleny v jednom souboru, tak je tam obsažen i kód, který se nemusí využít. Pokud by byly zabaleny samostatně, tak by se nepotřebné moduly (předpokládám) vůbec nenačetly.

    před 16 lety | reagoval [9] David Grudl [12] pmg
  9. David Grudl #9

    avatar

    #8 Jane Tvrdíku, V případě Texy se právě použíjí téměř všechny soubory. U dibi se sice obvykle použije jen jeden z ovladačů, nicméně i tak mi vychází rychlejší načíst vše v minimalizované formě.

    před 16 lety
  10. Ondrej Ivanic #10

    Používání kompaktních verzí se ujalo a od té doby většina bugreportů hlásila chybu na řádce 1

    Tak toto musi byt peklo :)

    Je jednosuborove Texy rychlejsie ako viac suborove Texy + op. cache (napr. APC)? Ak to tak nie je potom sa mi to zda ako zbytocna komplikacia urobit jeden subor (jednosuborove + op cache bude asi najrychlejsie, ale …)

    před 16 lety
  11. v6ak #11

    Bude fajn, až bude PhpMinAdmin distribuován jako index.phar 😁

    před 16 lety
  12. pmg #12

    #8 Jane Tvrdíku, PHP načte jen hlavičku archivu se seznamem souborů a vlastní kód čte, až když je potřeba. Důležité je, že má po celou dobu otevřený jen jeden soubor, ve kterém se přesouvá. Taková je má představa.

    Přesná struktura archivu se dá vyčíst ze zdrojů PEAR pakáže PHP Archive. Letmo jsem na to kouknul a myslím, že je nejlepší jednotlivé soubory před archivací prohnat ještě PHP bytecode Compilerem.

    před 16 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.


phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.