Twig: versnel het genereren van zijn sjablonen
Webbureau » Digitaal nieuws » Twig: versnel het genereren van zijn sjablonen

Twig: versnel het genereren van zijn sjablonen

Onlangs vroeg ik mezelf om na te denken over de oplossingen die Twig biedt om toegang te krijgen tot de eigenschappen van een object of een array.

Toegang krijgen tot een eigenschap van een object

Twig is ontworpen om onze sjablonen te vereenvoudigen, zowel qua code als qua netheid. Het is ook ontworpen om integrators, mensen die niet allemaal over ontwikkelingskennis beschikken, gemakkelijk toegang te geven tot de eigenschappen van een of ander object. Dit dankzij een vereenvoudigde syntaxis.

Pas toen, vooral ontwikkelaar zijnde, stelde ik mezelf de vraag hoe het met twig ging om te bepalen welke methode van een object moest worden aangeroepen.

Twig-syntaxis

In mijn volgende code ga ik ervan uit dat ik een klasse zoals hieronder gebruik.

1
2
3
4
5
6
7
8
9
10
11
12
13
klasse Object
{
privaat $Naam;
publiek $gebruikersnaam;
publiek functie getNaam() {
terugkeer $ This->naam;
}
publiek functie getGebruikersnaam() {
terugkeer $ This->gebruikersnaam;
}
}

Dit is hoe ik mijn sjabloon zal aanroepen vanaf een Symfony-controller.

1
2
3
publiek functie indexActie() {
terugkeer reeks("voorwerp" => $voorwerp);
}

Tot nu toe is alles duidelijk. Mijn object lijkt precies op de objecten die ik in mijn projecten kan gebruiken.

Verklaringen parseren in Twig

1
{{ object.name }}

Vanaf nu zullen we zien hoe Twig werkt met onze oproepen. Hier vragen we Twig om de waarde te nemen naam van mijn object, behalve dat voor Twig, wat uiteindelijk slechts een eenvoudige PHP-aanroep is, deze variabele ontoegankelijk is. Twig heeft daarom een ​​proxy toegevoegd om te abstraheren en te kijken welke eigenschappen en methoden beschikbaar zijn.

Twig zal daarom in onderstaande volgorde vragen om controles uit te voeren op het object.

  1. Kijken of object is een array en als naam is een sleutel;
  2. Kijken of object is een object en als naam is een toegankelijk attribuut;
  3. Kijken of object is een object en als naam is een methode;
  4. Kijken of object is een object en als getNaam is een methode;
  5. Kijken of object is een object en als is naam is een methode.
    Hier, met de notatie die we gebruikten, moesten we wachten tot de 4e voorwaarde bij ons element was aangekomen. Omdat naam is geen toegankelijk attribuut, noch een methode.

    1
    {{ object.username }}

In dit geval proberen we toegang te krijgen gebruikersnaam. Dit attribuut is een openbaar attribuut (in Symfony kwam ik dit zelden tegen). We moeten wachten op de 2e voorwaarde.

1
{{ object.getName() }}

In ons derde geval probeer ik mijn methode rechtstreeks aan te roepen. Ik krijg mijn resultaat van de derde conditie, wat een snellere conditie is.

1
{{ object.getUsername() }}

In ons vierde en laatste geval probeer ik mijn methode rechtstreeks te gebruiken. Ik haal mijn resultaat uit de derde voorwaarde. In dit geval heb ik een extra voorwaarde gesteld om toegang te krijgen tot mijn waarde.

Twig-sjablonen interpreteren

Toen ik naar dit detail keek, dacht ik na over hoe de ontwikkelaars van Twig de caching en de compilatie van de sjablonen hadden kunnen doen. Het duurde niet lang voordat ik tot de conclusie kwam dat met de weinige informatie en de vrijheid die de sjabloonbeheerder biedt, onze bestanden gewoon in PHP worden getranscribeerd op een vergelijkbare manier als wat we volledig zouden kunnen doen. Je kunt het ook zelf zien door in je cachemap te kijken.

1
2
{# Sjabloontak #}
{{ object.name }}
Sjabloon geïnterpreteerd in PHP
1
echo twig_escape_filter($this->env, $this->getAttribute((isset($context["object"]) ? $context["object"] : $this->getContext($context, "object")), "naam"), "html", null, waar);

Het eerste blok komt overeen met wat ik in mijn twig-sjabloon heb genoteerd, het tweede blok komt overeen met de vertaalde versie die ik in de cachemap vond.

We merken op dat de branch is vertaald in PHP, maar dat geen enkel element heeft toegestaan ​​om te voorspellen welke methode precies moet worden aangeroepen. De methode branch_escape_filter kan worden vergeleken met een proxy. Het is in deze methode dat we zullen bepalen hoe we toegang krijgen tot het attribuut.

Conclusie

Hoewel twig-sjablonen automatisch worden gecached door Symfony, wordt alleen de PHP-versie bewaard, maar zonder interpretatie van wat u wilt ophalen. In theorie zijn er dus hier de middelen om oproepen en de generatietijd van onze sjablonen te optimaliseren, omdat de verificatie bij elke oproep wordt uitgevoerd.

criterium

Ik wilde nog steeds een idee hebben over de winst die kan worden behaald door de methoden te noemen in plaats van " alias .

In een eerste geval roep ik een sjabloon aan die 10 keer hetzelfde object aanroept dat op zijn beurt 25 aliassen aanroept. Dit komt overeen met 250 oproepen. De resultaten worden vergroot door de lus van 10 om nauwkeurige berekeningen van de prestatiewinst mogelijk te maken.

Ten tweede roep ik een template aan die 10 keer hetzelfde object aanroept en die op zijn beurt 25 methodes aanroept (altijd via dezelfde proxy als voor de aliassen). Dat is weer 250.

Ik heb deze sjablonen elk 5 keer aangeroepen.

Merk op dat alle aanroepen naar de sjabloon die methoden aanroepen sneller zijn. Door de gemiddelden te nemen, zien we dat de sjabloon die aliassen gebruikt 54,6 milliseconden langer is (197.4 – 142.8).

Door een snelle berekening uit te voeren, merken we dat als we het terugbrengen tot een algemeen geval, de sjabloon die aanroepen naar methoden gebruikt gemiddeld sneller is op dezelfde gegevens met ongeveer 26.7%. Dit kan interessant zijn wanneer u veel objecten aanroept.

Dit tweede artikel volgt op een eerste bericht met snelle oplossingen om het genereren van sjablonen te optimaliseren. Het is het resultaat van optimalisatie die al wordt gebruikt op sites in productie die een te hoge latentietijd hadden.

Wij gebruiken alles omvat de Takje om onze opvattingen te verschuiven of te beïnvloeden. Maar misschien heb je nooit begrepen waarom we de mogelijkheid hadden om parameters door te geven, terwijl een standaard include variabelen erft van de huidige context.

1
{% omvatten "ProjectMyBundle:Sub:template.html.twig" %}

Vaak gebruiken we deze notatie. In dit geval geeft de include een kopie van al onze variabelen aan onze sjabloon. Dit is niet altijd nodig, en we hebben het fout om al onze variabelen te kopiëren.

Belang van de "enige" optie

Ik heb me lang afgevraagd wat het nut was van deze optie. Bovendien moet gezegd worden dat de documentatie niet veel informatie geeft. U kunt de Twig inclusief documentatie bekijken. Het geeft weinig element maar het geeft vooral een nadeel en geen voordeel: het moeten stellen zonder bepaalde variabelen. Zo bezien is het niet rendabel; waarom ik het zou moeten doen zonder enkele variabelen.

Laten we onze include implementeren! Laten we zeggen dat onze basissjabloon 5 variabelen heeft en ik voeg een sjabloon toe die slechts één van deze variabelen gebruikt, dit is de notatie die de voorkeur heeft.

1
{% omvatten "ProjectMyBundle:Sub:template.html.twig" met alleen {"object": myVar} %}

Op deze manier is alleen een "object"-variabele beschikbaar in mijn sjabloon. Dit beperkt het kopiëren van nutteloze variabelen en daarmee de geheugentoewijzing (bespaart tijd en geheugengebruik).

Code en use-cases

1
2
3
4
5
6
// Beheerder
// Hier genereert het een sjabloon door een imposante variabele (een verzameling) door te geven die alle objecten voor een bepaalde tabel bevat
publiek functie testActie() {
$objecten = $ This->container->krijgen(“doctrine.orm.default_entity_manager”)->getRepository(“ProjectMijnBundel:Test”)->Alles zoeken();
terugkeer reeks("items" => $objecten);
}

We doorlopen onze verzameling en geven elke iteratie van de verzameling een sjabloon aan de sjabloon. In dit geval worden elke keer dat we de integratie van een sjabloon aanvragen, alle variabelen gekopieerd, evenals de variabelen waarmee is doorgegeven de optie "met".. In ons eerste geval zouden we ons heel goed kunnen voorstellen dat we toegang hebben tot onze verzameling (objecten) en onze huidige iteratie (object).

1
2
3
4
5
{#Sjabloon 1#}
{% For object in objecten %}
{% omvatten "ProjectMyBundle:Sub:template.html.twig" met {"object": object} %}
{% einde voor %}

In ons tweede geval activeer ik de optie alleen waarmee u alleen de variabelen kunt kopiëren die als parameters zijn doorgegeven. Eenvoudig ?

1
2
3
4
5
{#Sjabloon 2#}
{% For object in objecten %}
{% omvatten "ProjectMyBundle:Sub:template.html.twig" met alleen {"object": object} %}
{% einde voor %}

criterium

Ik heb de tests uitgevoerd met de sjablonen en de code uit het bovenstaande gedeelte. Ik presteerde met 5 iteraties van elke sjabloon, waarbij ik eraan dacht om de cache voor elke eerste test te legen.

Met deze grafiek kunnen we zien dat het laden over het algemeen langer is voor degenen die de optie niet gebruiken alleen. Het verschil wordt meestal kleiner na het cachen. Dit komt doordat mijn sjabloon klein is en er weinig variabelen worden gebruikt. In meer toegepaste gevallen zijn er winsten tot 30%.

Hier, als we de waarden middelen, bereiken we een gemiddeld verschil van 9 ms (48,6 – 39,6 = 9). We kunnen daarom een ​​geschatte winst van 20% berekenen, zelfs als dit in ons geval in perspectief moet worden geplaatst, aangezien de eerste opname vreselijk lang is zonder het gebruik van " alleen .

★ ★ ★ ★ ★