Twig: påskynda genereringen av dess mallar
Webbyrå » Digitala nyheter » Twig: påskynda genereringen av dess mallar

Twig: påskynda genereringen av dess mallar

Nyligen bad jag mig själv att reflektera över de lösningar som Twig erbjuder för att komma åt egenskaperna hos ett objekt eller en array.

Tillgång till en egenskap hos ett objekt

Twig designades för att förenkla våra mallar, både vad gäller kod och renlighet. Den har också utformats för att ge integratörer, personer som inte alla har utvecklingskunskap, enkel tillgång till egenskaperna hos ett objekt eller andra. Detta tack vare en förenklad syntax.

Först då, som utvecklare framför allt, ställde jag mig frågan om hur twig gjorde för att avgöra vilken metod för ett objekt som skulle kallas.

Kvistsyntax

I min följande kod kommer jag att anta att jag använder en klass som nedan.

1
2
3
4
5
6
7
8
9
10
11
12
13
klass Ändamålet
{
privat $Name;
allmän $användarnamn;
allmän fungera hämta namn() {
avkastning $ detta->namn;
}
allmän fungera getUsername() {
avkastning $ detta->användarnamn;
}
}

Så här kommer jag att kalla min mall från en Symfony-kontroller.

1
2
3
allmän fungera indexAction() {
avkastning array("objekt" => $objekt);
}

Än så länge är allt klart. Mitt objekt ser ut precis som de objekt jag kan använda i mina projekt.

Parsande deklarationer i kvist

1
{{ object.name }}

Från och med nu kommer vi att se hur Twig fungerar med våra samtal. Här ber vi Twig ta värdet namn av mitt objekt, förutom att för Twig som bara är ett enkelt PHP-anrop i slutändan, är denna variabel otillgänglig. Twig har därför lagt till en proxy för att abstrahera och se vilka egenskaper och metoder som finns.

Twig kommer därför att be i nedanstående ordning att göra kontroller på föremålet.

  1. Se om objektet är en array och om namn är en nyckel;
  2. Se om objektet är ett objekt och om namn är ett tillgängligt attribut;
  3. Se om objektet är ett objekt och om namn är en metod;
  4. Se om objektet är ett objekt och om hämta namn är en metod;
  5. Se om objektet är ett objekt och om är namn är en metod.
    Här, med notationen vi använde, var vi tvungna att vänta på att det 4:e villkoret skulle komma fram till vårt element. Därför att namn är inte ett tillgängligt attribut eller en metod.

    1
    {{ object.username }}

I det här fallet försöker vi komma åt Användarnamn. Det här attributet är ett offentligt attribut (i Symfony stötte jag sällan på det här fallet). Vi måste vänta på det andra villkoret.

1
{{ object.getName() }}

I vårt tredje fall försöker jag ringa min metod direkt. Jag får mitt resultat från det tredje tillståndet, vilket är ett snabbare tillstånd.

1
{{ object.getUsername() }}

I vårt fjärde och sista fall försöker jag använda min metod direkt. Jag får mitt resultat från det tredje tillståndet. I det här fallet sätter jag ett ytterligare villkor för att komma åt mitt värde.

Tolkning av kvistmallar

När jag tittade på denna detalj tänkte jag på hur utvecklarna av Twig kunde ha gjort cachningen och sammanställningen av mallarna. Det tog inte lång tid för mig att komma till slutsatsen att med den lilla information och den frihet som mallhanteraren erbjuder, transkriberas våra filer helt enkelt till PHP på ett liknande sätt som vi helt skulle kunna göra. Du kan också se själv genom att titta i din cachemapp.

1
2
{# Mallgren #}
{{ object.name }}
Mall tolkad i PHP
1
echo twig_escape_filter($this->env, $this->getAttribute((isset($context["object"]) ? $context["object"] : $this->getContext($context, "object")), "namn"), "html", null, sant);

Det första blocket matchar det jag noterade i min kvistmall, det andra blocket matchar den översatta versionen jag hittade i cachemappen.

Vi noterar att grenen har översatts till PHP men att inget element har tillåtit den att förutsäga vilken metod som ska anropas exakt. Metoden branch_escape_filter kan jämföras med en proxy. Det är i denna metod som vi kommer att bestämma hur vi kommer åt attributet.

Slutsats

Även om kvistmallar automatiskt cachelagras av Symfony, är det bara PHP-versionen som behålls men utan tolkning av vad du vill hämta. I teorin finns det därför här möjligheten att optimera samtal och genereringstiden för våra mallar eftersom verifieringen utförs vid varje samtal.

riktmärke

Jag ville fortfarande ha en uppfattning om vilka vinster som kan göras genom att kalla metoderna snarare än " alias ".

I ett första fall anropar jag en mall som kommer att anropa 10 gånger samma objekt som i sin tur anropar 25 alias. Detta motsvarar 250 samtal. Resultaten förstoras med slingan på 10 för att möjliggöra exakta beräkningar av prestandavinsten.

För det andra anropar jag en mall som kommer att anropa samma objekt 10 gånger och som i sin tur anropar 25 metoder (alltid via samma proxy som för aliasen). Det är 250 igen.

Jag ringde dessa mallar 5 gånger vardera.

Observera att alla anrop till mallen som gör anrop till metoder är snabbare. Genom att ta medelvärden märker vi att mallen som använder alias är längre med 54,6 millisekunder (197.4 – 142.8).

Genom att göra en snabb beräkning märker vi att om vi reducerar det till ett generellt fall är mallen med anrop till metoder snabbare i genomsnitt på samma data med cirka 26.7 %. Detta kan vara intressant när man ringer många objekt.

Den här andra artikeln följer ett första inlägg som ger snabba lösningar för att optimera genereringen av mallar. Det är frukten av optimering som redan används på anläggningar i produktion som hade för hög latenshastighet.

Vi använder alla innefattar de Kvist att förändra eller faktorisera våra åsikter. Men du kanske aldrig förstod varför vi hade möjligheten att skicka parametrar, när en grundläggande inkludering ärver variabler från det aktuella sammanhanget.

1
{% innefattar “ProjectMyBundle:Sub:template.html.twig” %}

Ofta använder vi denna notation. I det här fallet kommer include att ge en kopia av alla våra variabler till vår mall. Detta är inte alltid nödvändigt, och vi har fel när vi kopierar alla våra variabler.

Intresset för det "enda" alternativet

Jag undrade länge vad som var poängen med det här alternativet. Dessutom måste det sägas att dokumentationen inte ger så mycket information. Du kan ta en titt på dokumentationen som innehåller Twig. Det ger lite element men det ger särskilt en nackdel och ingen fördel: att klara sig utan vissa variabler. Sett på detta sätt är det inte lönsamt; varför jag ska göra utan några variabler.

Låt oss implementera vår inkluderar! Låt oss säga att vår basmall har 5 variabler och jag inkluderar en mall som bara använder en av dessa variabler, detta är notationen som kommer att vara att föredra.

1
{% innefattar "ProjectMyBundle:Sub:template.html.twig" med endast {"object": myVar} %}

På detta sätt kommer endast en "objekt"-variabel att vara tillgänglig i min mall. Detta begränsar kopieringen av värdelösa variabler, och därför av minnesallokering (sparar tid och minnesförbrukning).

Koda och använda fall

1
2
3
4
5
6
// Controller
// Här genererar den en mall genom att skicka en imponerande variabel (en samling) som innehåller alla objekt för en given tabell
allmän fungera testAction() {
$objekt = $ detta->behållare->få("doctrine.orm.default_entity_manager")->getRepository("ProjectMyBundle:Test")->findAll();
avkastning array("artiklar" => $objekt);
}

Vi loopar över vår samling och vi ger en mall varje iteration av samlingen till mallen. I det här fallet, varje gång vi kräver integration av en mall, kopieras alla variabler såväl som de som skickas med alternativet "med".. I vårt första fall skulle vi mycket väl kunna tänka oss att komma åt vår samling (objekt) såväl som vår nuvarande iteration (objekt).

1
2
3
4
5
{#Mall 1#}
{% för objekt i objekt %}
{% innefattar "ProjectMyBundle:Sub:template.html.twig" med {"object": object} %}
{% endfor %}

I vårt andra fall aktiverar jag alternativet endast som låter dig kopiera endast de variabler som skickas som parametrar. Lätt ?

1
2
3
4
5
{#Mall 2#}
{% för objekt i objekt %}
{% innefattar "ProjectMyBundle:Sub:template.html.twig" med endast {"object": object} %}
{% endfor %}

riktmärke

Jag utförde testerna med mallarna och koden som ges i delen ovan. Jag utförde med 5 iterationer av varje mall, kom ihåg att tömma cachen innan varje första test.

Med denna graf kan vi se att belastningen generellt sett är längre för de som inte använder alternativet endast. Skillnaden tenderar att minska efter cachning. Detta beror på att min mall är liten och få variabler används. I mer tillämpade fall är det vinster på upp till 30 %.

Här, om vi gör ett medelvärde av värdena, når vi en medelskillnad på 9 ms (48,6 – 39,6 = 9). Vi kan därför beräkna en ungefärlig vinst på 20% även om detta ska sättas i perspektiv i vårt fall eftersom det första skottet är fruktansvärt långt utan användning av " endast ".

★ ★ ★ ★ ★