Twig: gyorsítsa fel a sablonok generálását
Nemrég felkértem magam, hogy reflektáljak a Twig által kínált megoldásokra egy objektum vagy egy tömb tulajdonságainak eléréséhez.
Hozzáférés egy objektum egy tulajdonságához
A Twig célja a sablonok egyszerűsítése volt, mind a kód, mind a tisztaság szempontjából. Arra is tervezték, hogy az integrátorok, olyan emberek számára, akik nem rendelkeznek fejlesztési ismeretekkel, könnyen hozzáférhessenek egy objektum vagy mások tulajdonságaihoz. Ez az egyszerűsített szintaxisnak köszönhető.
Csak ezután, mindenekelőtt fejlesztő lévén, feltettem magamnak a kérdést, hogy a twig hogyan tudja meghatározni, hogy egy objektum melyik metódusát hívja meg.
Twig szintaxis
A következő kódomban azt feltételezem, hogy az alábbihoz hasonló osztályt használok.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
osztály tárgy
{
magán $Name;
nyilvános $felhasználónév;
nyilvános funkció getName() {
visszatérés $ ezt->név;
}
nyilvános funkció getUsername() {
visszatérés $ ezt->felhasználónév;
}
}
|
Így fogom hívni a sablonomat egy Symfony vezérlőről.
1
2
3
|
nyilvános funkció indexAction() {
visszatérés sor("tárgy" => $objektum);
}
|
Eddig minden világos. Az objektum pontosan úgy néz ki, mint a projektjeimben használható objektumok.
Deklarációk elemzése a Twigben
1
|
{{ object.name }}
|
Mostantól meglátjuk, hogyan működik a Twig a hívásainkkal. Itt megkérjük Twig-et, hogy vegye fel az értéket név az objektumról, kivéve, hogy a Twig esetében, amely végül csak egy egyszerű PHP hívás, ez a változó nem érhető el. A Twig ezért hozzáadott egy proxyt az elvonatkoztatáshoz, és megtekintheti, milyen tulajdonságok és módszerek állnak rendelkezésre.
A Twig ezért az alábbi sorrendben kéri, hogy ellenőrizze az objektumot.
- Hátha tárgy egy tömb és ha név egy kulcs;
- Hátha tárgy egy tárgy és ha név elérhető attribútum;
- Hátha tárgy egy tárgy és ha név egy módszer;
- Hátha tárgy egy tárgy és ha getName egy módszer;
- Hátha tárgy egy tárgy és ha isName egy módszer.
Itt az általunk használt jelöléssel meg kellett várnunk, hogy a 4. feltétel megérkezzen elemünkhöz. Mert név nem elérhető attribútum, és nem is metódus.1{{ object.username }}
Ebben az esetben megpróbálunk hozzáférni felhasználónév. Ez az attribútum nyilvános attribútum (a Symfonyban ritkán találkoztam ezzel az esettel). Meg kell várnunk a 2. feltételt.
1
|
{{ object.getName() }}
|
Harmadik esetünkben megpróbálom közvetlenül hívni a módszeremet. Az eredményt a harmadik feltételből kapom, ami egy gyorsabb állapot.
1
|
{{ object.getUsername() }}
|
Negyedik és utolsó esetünkben megpróbálom közvetlenül alkalmazni a módszeremet. A harmadik feltételből kapom meg az eredményt. Ebben az esetben további feltételt szabok az értékem eléréséhez.
Twig sablonok értelmezése
Amikor ezt a részletet megnéztem, azon gondolkodtam, hogy a Twig fejlesztői hogyan tudták volna elvégezni a gyorsítótárat és a sablonok összeállítását. Nem kellett sok idő ahhoz, hogy arra a következtetésre jutottam, hogy a kevés információval és a sablonkezelő által kínált szabadsággal a fájljaink egyszerűen átkerülnek PHP-be, hasonlóan ahhoz, amit teljesen megtehetnénk. Ön is meggyőződhet róla, ha megnézi a gyorsítótár mappáját.
1
2
|
{# Sablon ág #}
{{ object.name }}
|
1
|
echo twig_escape_filter($this->env, $this->getAttribute((isset($context["object"]) ? $context["object"] : $this->getContext($context, "object")), „név”), „html”, null, igaz);
|
Az első blokk megegyezik azzal, amit a gallysablonban megjegyeztem, a második blokk a gyorsítótár mappájában talált lefordított verzióval.
Megjegyezzük, hogy az ágat lefordították PHP-re, de egyetlen elem sem tette lehetővé, hogy megjósolja, melyik metódust kell pontosan hívni. A módszer branch_escape_filter proxyhoz lehetne hasonlítani. Ebben a módszerben határozzuk meg, hogyan érjük el az attribútumot.
Következtetés
Bár a gallysablonokat a Symfony automatikusan gyorsítótárba helyezi, csak a PHP-verziót tartja meg, de a lekérni kívánt értelmezés nélkül. Elméletileg tehát itt van a hívások optimalizálásának eszköze és a sablonjaink generálási ideje, mivel az ellenőrzést minden hívásnál elvégezzük.
benchmark
Még mindig szerettem volna egy elképzelést arról, hogy milyen előnyök érhetők el a metódusok meghívásával, nem pedig " álnév ".
Az első esetben meghívok egy sablont, amely 10-szer hívja meg ugyanazt az objektumot, amely 25 álnevet hív meg. Ez 250 hívást jelent. Az eredményeket a 10-es hurokkal felnagyítja, hogy pontos számításokat lehessen végezni a teljesítménynövekedéssel kapcsolatban.
Másodszor, meghívok egy sablont, amely 10-szer hívja meg ugyanazt az objektumot, amely viszont 25 metódust hív meg (mindig ugyanazon a proxyn keresztül, mint az álneveknél). Ez megint 250.
Ezeket a sablonokat egyenként ötször hívtam meg.
Vegye figyelembe, hogy a sablon minden hívása, amely metódusokat hív meg, gyorsabb. Az átlagokat vesszük észre, hogy az álneveket használó sablon 54,6 ezredmásodperccel hosszabb (197.4 – 142.8).
Egy gyors számítással észrevesszük, hogy ha általános esetre redukáljuk, akkor a metódushívásokat használó sablon átlagosan körülbelül 26.7%-kal gyorsabb ugyanazon az adatokon. Ez érdekes lehet, ha sok objektumot hívunk meg.
Ez a második cikk egy első bejegyzést követ, amely gyors megoldásokat kínál a sablonok generálásának optimalizálására. Ez a túl magas késleltetésű telephelyeken már alkalmazott optimalizálás gyümölcse.
Mindet használjuk magában foglalja a de Gally hogy megváltoztassuk vagy befolyásoljuk nézeteinket. De talán soha nem értetted, miért volt lehetőségünk paramétereket átadni, amikor az alap include örökli a változókat az aktuális környezetből.
1
|
{% tartalmaz „ProjectMyBundle:Sub:template.html.twig” %}
|
Gyakran használjuk ezt a jelölést. Ebben az esetben az include minden változónk másolatát adja a sablonunkhoz. Ez nem mindig szükséges, és tévedünk, ha az összes változónkat másoljuk.
Az "egyetlen" lehetőség érdeke
Sokáig gondolkodtam, mi értelme ennek a lehetőségnek. Emellett azt kell mondani, hogy a dokumentáció nem ad sok információt. Megtekintheti a Twig dokumentációját. Kevés elemet ad, de különösen hátrányt és előnyt nem ad: bizonyos változók nélkül lenni. Így nézve nem jövedelmező; miért kellene nélkülöznöm néhány változót.
Valósítsuk meg tartozékainkat! Tegyük fel, hogy az alapsablonunknak 5 változója van, és beleteszek egy olyan sablont, amely csak egyet használ ezek közül a változók közül, ez az a jelölés, amely előnyösebb lesz.
1
|
{% tartalmaz "ProjectMyBundle:Sub:template.html.twig" with {"object": myVar} csak %}
|
Ily módon csak egy "objektum" változó lesz elérhető a sablonomban. Ez korlátozza a haszontalan változók másolását, és ezáltal a memóriafoglalást (idő- és memóriafelhasználás megtakarítása).
Kód és használati esetek
1
2
3
4
5
6
|
// Vezérlő
// Itt egy sablont generál egy impozáns változó (egy gyűjtemény) átadásával, amely tartalmazza az adott tábla összes objektumát
nyilvános funkció testAction() {
$objektumok = $ ezt->container->get(„doctrine.orm.default_entity_manager”)->getRepository(„ProjectMyBundle:Test”)->mindent megtalál();
visszatérés sor(„elemek” => $objektumok);
}
|
Végighurkoljuk a gyűjteményünket, és a gyűjtemény minden egyes iterációjában sablont adunk a sablonhoz. Ebben az esetben minden alkalommal, amikor egy sablon integrálását kérjük, az összes változót másoljuk, valamint a a "val" opciót. Első esetünkben nagyon jól el tudnánk képzelni, hogy elérjük a gyűjteményünket (objektumainkat), valamint az aktuális iterációnkat (objektumunkat).
1
2
3
4
5
|
{#1. sablon#}
{% mert objektum az objektumokban %}
{% tartalmaz "ProjectMyBundle:Sub:template.html.twig" with {"object": object} %}
{% endfor %}
|
Második esetünkben aktiválom az opciót csak amely lehetővé teszi csak a paraméterként átadott változók másolását. Könnyű ?
1
2
3
4
5
|
{#2. sablon#}
{% mert objektum az objektumokban %}
{% tartalmaz "ProjectMyBundle:Sub:template.html.twig" csak {"object": object} mellett %}
{% endfor %}
|
benchmark
A teszteket a fenti részben megadott sablonokkal és kóddal végeztem el. Mindegyik sablon 5 iterációjával végeztem, emlékezve arra, hogy minden első teszt előtt ürítsem ki a gyorsítótárat.
Ezen a grafikonon láthatjuk, hogy azok számára, akik nem használják a lehetőséget, általában hosszabb a betöltés csak. A különbség a gyorsítótárazás után csökken. Ez annak köszönhető, hogy a sablonom kicsi, és kevés változót használnak. Több alkalmazott esetben akár 30%-os nyereség is elérhető.
Itt, ha átlagoljuk az értékeket, átlagosan 9 ms-os különbséget érünk el (48,6 – 39,6 = 9). Ezért akkor is számíthatunk hozzávetőlegesen 20%-os nyereséget, ha ezt a mi esetünkben perspektívába vesszük, mivel az első felvétel rettenetesen hosszú a „ csak ".