Om phpro.be nog beter te maken, gebruiken wij functionele en analytische cookies.
Wil je meer weten over de cookies? Klik dan op de knop "Voorkeuren".
Tijdens mijn onderzoek naar Blackfire (https://blackfire.io) en de functionaliteit ervan, heb ik besloten om me te richten op de categorie pagina's van Magento 1. Categoriepagina's worden het meest gevraagd in het hele framework, dus elke prestatieverbetering resulteert in een betere gebruikerservaring bij het navigeren door de productencatalogus.
Nadat ik het eerste profiel op mijn lokale projectomgeving, die alleen gebruik maakt van configureerbare producten, heb ik de volgende resultaten ontvangen:
We zien dat ons profiel een wandkloktijd heeft van 15,8 seconden, wat teleurstellend langzaam is. De wandkloktijd is een berekening van uw CPU (hoeveelheid tijd die gebruikt wordt voor verwerkingsinstructies) + de I/O-tijd (netwerk + schijftijd). Met deze resultaten vraagt onze pagina om verder onderzoek.
Hieronder een screenshot van alle functies en subfuncties van de getConfigurableAttributes functie, met een duidelijk rood pad om te volgen.
We zien nu dat onze getConfigurableAttributes functie 3 callees heeft, functies die vanuit de huidige functie worden aangeroepen. Een van deze functies is de Varien_Data_Collection_Db::load functie, die 98% van alle beltijd gebruikt. Een vraag die we onszelf kunnen stellen: "Waarom is Magento 21 collecties aan het laden en is dit noodzakelijk?"
We zien dat het laden van een collection class telkens de afterload functie activeert, die weer andere functies aanroept en zo verder.... Aan het eind van ons pad zien we dat de attributesCompare functie 39,65% van alle tijden gebruikt en 31122 keer wordt genoemd.
Laten we elke belangrijke functie op het pad nader bekijken zodat we een beter begrip hebben van wat er gebeurt en waarom attributenVergelijken zo vaak wordt genoemd. We beginnen met de functie getAttributeById in de 'Mage_Catalog_Model_Model_Product_Type_Abstract' klasse.
Het enige wat deze functie doet, is de getSetAttributes aanroepen om alle attributen voor een specifiek product te ontvangen. Het loops alle attributen tot het attribuut is gevonden dat overeenkomt met de attributeId parameter. Als het gevonden wordt, geeft het het attribuut terug. We weten dat de getSetAttributes functie de volgende belangrijke functie op ons pad is, dus gaan we verder met ons onderzoek door daar te kijken.
Deze functie geeft alle producten van een specifiek product terug met de loadAllAttributes functie, maar roept ook de getSortedAttributes functie op. Dat is het grootste probleem zoals we kunnen concluderen uit ons Blackfire profiel (47,23%).
Deze functie controleert welke attributen zich in de bijgeleverde attributenset bevinden en sorteert ze met de uasort functie die op zijn attributesCompare aanroept. Zoals eerder gezegd, is deze functie de eindfunctie op ons pad en moet verbeterd worden. We weten dat deze functie voor elk product herhaald wordt, wat nutteloos is, omdat een specifieke attributenset altijd dezelfde attributenvolgorde zal behouden voor elk product dat die set gebruikt. Laten we proberen deze functionaliteit te herschrijven.
Helaas bevindt deze functie zich in een abstracte Magento klasse, dus een goede herschrijving is niet mogelijk. In plaats daarvan moeten we de hele klasse overschrijven. Dit doen we door de 'Mage_Eav_Model_Entity_Abstract' klasse in de 'app/code/local' pool op hetzelfde bestandspad te plaatsen als het bestand in de 'app/code/core' code pool.
Eerst voegen we een statische variabele toe. Deze variabele wordt gebruikt bij de eerste keer dat de attributen gesorteerd worden en bewaart de resultaten op een specifieke attributeset-id-index. Op deze manier hoeven we de posities van deze attributen niet meer te berekenen wanneer dezelfde attributenet-id wordt opgegeven. We geven alleen de dataset van onze variabele terug.
Vervolgens wijzigen we de functie getSortedAttributes en brengen we de volgende wijzigingen aan.
We controleren of onze sleutel bestaat. Zo ja, dan sturen we de gegevens terug. Zo niet, dan berekenen we het en stellen we de array index aan het eind in voor verder gebruik.
Laten we onze pagina opnieuw profileren en kijken of de wijzigingen effect hebben gehad.
We zien een verbetering van 45% wandkloktijd op onze hele pagina! Onze CPU tijd is verminderd met 48%.
Hierboven een vergelijking van de twee profielen. Het vorige en huidige profiel. De blauwe blokken geven verbeteringen aan met de wandkloktijd in seconden. Een eenvoudige verandering met grote effecten. Natuurlijk is het ook mogelijk om het profiel niet in vergelijkingsmodus te bekijken.
Verdere verbeteringen zouden kunnen zijn om de collectie één keer te laden voor alle producten in plaats van 21 keer apart. Het probleem boven aan onze rode weg aanpakken, is meestal een beter idee omdat elke subfunctie volgt. Omdat in dit geval elk product verschillende configureerbare attributen kan hebben, is dit misschien niet het beste idee. Let op: dit is niet de standaard list.phtml Magento template. In tegenstelling tot deze template is de functie getSortedAttributes de kern van de Magento functionaliteit en kan een snelle winst zijn voor verschillende Magento projecten.
Dit probleem was vooral een CPU probleem, maar je kunt ook andere factoren hebben die problemen kunnen veroorzaken. Het is een goed idee om alle tabbladen te controleren. Geheugen, Netwerk, Http, Http, Queries, etc.... Een goed voorbeeld zijn import/export scripts. Deze kunnen gemakkelijk CPU problemen veroorzaken, maar ook geheugenproblemen. Laat me je een voorbeeld geven van een ander geval. Dit keer over een Magento's varien core bestand.
Bij het importeren van productafbeeldingen met een van Magento's cronjobs is een 'out of memory' fout gemaakt. Ik besloot dit keer om Blackfire's CLI te gebruiken, omdat cronjobs wel eens tijdrovend kunnen zijn. Vooral bij het verwerken van import scripts. Dit profiel werd gegenereerd met de gratis versie van Blackfire, dus sommige tabbladen hadden kunnen verdwijnen.
Boven het resultaat van ons profiel. Let op dat we dit keer onze gegevens onder het geheugen tabblad bekijken, want onze fout is geheugenspecifiek. Ons pad is nu lichtblauw in plaats van rood.
De meest tijdrovende functie is de imagecratefromjpeg die slechts 32 keer wordt aangeroepen. Deze 32 staat voor het aantal beelden dat geïmporteerd werd voordat de geheugenfout werd gegooid. We kunnen ook concluderen dat voor elke afbeelding een nieuwe instantie van de 'Varien_Image_Adapter_Gd2' wordt aangemaakt. De constructeur van het varien_image roept de open functie van deze klasse aan, die op zijn beurt de imagecreatefromjpeg aanroept.
Al deze afbeeldingen worden gemaakt en bewaard in het geheugen, maar nergens uit het geheugen verwijderd.
Het is dus duidelijk dat deze na verloop van tijd een fout zullen maken. Vooral bij het importeren van veel beelden. Eens kijken hoe we het script zo kunnen aanpassen dat ons geheugen na elke import van een afbeelding weer wordt vrijgegeven.
Als we kijken naar de open functie van onze 'Varien_Image_Adapter_Gd2' klasse zien we dat de huidige afbeelding is opgeslagen in een variabele $_imageHandler.
Het zou een goed idee kunnen zijn om de image set in deze variabele te vernietigen nadat de class niet meer gebruikt wordt. Op dat moment is de image al geïmporteerd, dus we hebben deze niet meer nodig.
Laten we de 'Varien_Image_Adapter_Gd2' klasse uit onze Magento 1 lib directory overschrijven door dezelfde klasse toe te voegen onder het 'app/code/local/Varien/Image/Adapter/' pad.
Een goede plaats om onze functionaliteit te schrijven zou kunnen zijn in de destructor. Deze functie zal altijd worden aangeroepen tijdens de afsluitvolgorde van een bepaald object. We voegen de volgende code toe:
Hier activeren we de @imagedestroy functie op onze variabele. Door dit te doen wordt het image-object vernietigd en het geheugen vrijgegeven. Laten we ons script opnieuw profileren en de impact zien.
We zien nu dat ons geheugen is afgenomen met 209MB! Ook is elk product nu met succes geïmporteerd (meer dan 200 afbeeldingen) en het geheugen is stabiel gehouden, wat het belangrijkste is. We zijn er nu zeker van dat we ook grotere importen kunnen uitvoeren.
Ik hoop dat deze twee voorbeelden u de kracht van Blackfire laten zien bij het ontwikkelen van nieuwe code of het onderhouden van bestaande code.
Blackfire Silver Partner
PHPro is Blackfire.io Silver Partner. Blackfire stelt alle ontwikkelaars en IT/Ops in staat om continu hun applicatieprestaties te verifiëren en te verbeteren, gedurende de gehele levenscyclus, door op het juiste moment de juiste informatie te krijgen. Als u extra hulp nodig heeft, performance consultancy om uw PHP applicaties te verbeteren, aarzel dan niet om contact op te nemen met het PHPro PHP Performance Team.
Cookie policy
Om PHPro.be nog beter te maken, gebruiken wij functionele en analytische cookies. Informatie van deze website en jouw voorkeuren worden in deze cookies opgeslaan door jouw browser. Aan de hand van de cookies kunnen we herkennen dat je al eerder op de website bent geweest. Dit doen we conform onze privacy policy.
Functioneel
Functionele cookies zijn strikt noodzakelijke cookies om de goede werking van de website te garanderen. Meer informatie kan je terugvinden in onze cookie policy en privacy policy.
Analytisch
Hiermee sta je toe dat PHPro anonieme gegevens verzamelt over het gebruik van de website met third party cookies, zoals het aantal clicks op knoppen en het gedrag van bezoekers op de website. Daarnaast kunnen we via deze optie ook marketinggerelateerde acties uitvoeren. Meer informatie vind je in onze cookie policy en privacy policy.
Als je deze cookie activeert, dan help je ons om jouw ervaring van PHPro.be verder te verbeteren.
Marketing
Hiermee sta je toe dat PHPro via third party cookies marketinggerelateerde gegevens verzameld. Meer informatie vind je in onze cookie policy en privacy policy.
Als je deze cookie activeert, dan help je ons om jouw ervaring van PHPro.be verder te verbeteren.
Privacy Policy
Lees meer over het gebruik van cookies op deze website in onze privacy policy