300 % snabbare WordPress med transienter

Visste du att WordPress har ett inbyggt system för cache som kallas transienter? De är lätta att använda och kan vara extremt effektiva om man använder dem på rätt sätt. I denna artikel kommer jag att visa hur vi använde funktionerna i WP Transient API för att få startsidan på vår egen webbplats Seravo.com att i genomsnitt laddas över 300 % snabbare.

Cache kan vara svårt ibland eftersom utvecklaren behöver ha mycket djup förståelse för hela webbplatsen för att kunna välja bra värden för cachens giltighetstid och för hantering av hur cachen rensas. Men om du inte använder någon cache överhuvudtaget och inte använder några transientfunktioner någonstans på webbplatsen kan du vara säker på att du missar viktiga möjligheter att snabba upp din WordPress-installation.

WordPress transient-API: get_, set_ och delete_transient()

WordPress transient-API är extremt enkelt. Det innehåller endast tre funktioner: set (spara), get (hämta) och delete (radera). Med kommandot set sparar man något i sin cache, och med get hämtar man tillbaka det. Funktionen set (spara) tar tre parametrar: namnet på cache-objektet (betecknas ”cache key”, d.v.s. cachenyckel), värdet/innehållet som ska sparas i cachen, och en giltighetstid, angiven i antal sekunder. Kommandot get (hämta) är ännu enklare: man anger bara cachenyckeln till funktionen, så får man som svar det sparade värdet om det återfinns, eller det boolska värdet ”false” om ingenting hittades. Kommandot delete (radera) används för att göra en cachenyckel ogiltig, så att den raderas redan innan dess giltighetstid har löpt ut. Nedan visas det klassiska exemplet från WordPress-dokumentationen som visar hur en transient används för att spara resultatet av en databasfråga så att databasfrågan, som kanske kräver mycket datakraft, inte behöver köras varje gång:

<?php 
// Kontrollera transienten. Om ingen hittas körs WP_Query
if ( false === ( $featured = get_transient( 'foo_featured_posts' ) ) ) {

      $featured = new WP_Query(
       array(
        'category' => 'featured',
        'posts_per_page' => 5
       ));

    // Spara resultaten i en transient. Sätt giltighetstiden till 12 timmar.
    set_transient( 'foo_featured_posts', $featured, 12 * HOUR_IN_SECONDS );
} ?>

Vad ska man spara i en transient?

I en cache är det god idé att spara vad som helst, som kräver mycket datorkraft för att ta fram, där resultatet kommer att vara giltigt åtminstone en viss tid.

Fallstudie: startsidan för Seravo.com

Det finns två sätt som är att föredra för att analysera vad som händer i PHP-koden när en laddningen av en WordPress-sida  körs: XDebug och Tideways. På webbplatser i full drift är Tideways det enda vettiga alternativet. En manuellt initierad spårning av vår startsida Seravo.com gav oss nedanstående tidsdiagram som avslöjade var i koden den mesta körningstiden användes. Problemet var att mallfilerna hämtade en lång rad anpassade inläggstyper från databasen.

Nedan följer innehållet i den ursprungliga versionan av vår fil frontpage.php i WordPress-temat. Kort sagt laddade den in ett antal delmallar, som i sin tur innehöll viss standardkod och enkla loopar som stegade igenom olika anpassade inläggstyper. Tideways-profileringen visade att hämtandet av dessa delmallar belastade databasen ganska mycket. Med tanke på att startsidans innehåll är relativt statiskt och det enda som i princip ändras är de senaste blogginlägg är detta en god kandidat för cache.

<?php
get_header();
get_template_part( 'partials/fp', 'hero' );
get_template_part( 'partials/fp', 'features' );
get_template_part( 'partials/fp', 'segment-section' );
get_template_part( 'partials/fp', 'products' );
get_template_part( 'partials/fp', 'customers' );
get_template_part( 'partials/fp', 'blog-section' );
get_template_part( 'partials/fp', 'cta-section' );
get_template_part( 'partials/tech', 'logos-section' );
get_footer();

Vårt tillvägagångssätt var att skapa en ytterfunktion som skulle hämta mallan från cache om den hittas där. Och endast om malldelen inte hittades där skulle den faktiskt generera malldelen, spara resultatet med hjälp av utmatningsbufferten för PHP och sedan skriva ut malldelens innehåll som just genererats eller hämtats från cacheminnet. De inbakade kommentarerna i koden förklarar varje steg i detalj.

<?php
/*
 * Ytterfunktion (wrapper) för get_template_part för att hämta
 * en färdigrenderad mall från WP Transient-cache om den finns.
 *
 * Obs! Detta ska bara göras för statiska sidor som alltid har
 * samma innehåll, eller kan vara statiskt i åtminstone en timme
 * (vilket är den nuvarande giltighetstiden för cachen).
 */
function templateCache( $template_path, $template_name ) {
  if ( cntrst()->helpers->is_mobile() ) {
    $cache_key = 'seravo-partials-'. $template_name .'_mobile';
  } else {
    $cache_key = 'seravo-partials-'. $template_name;
  }
  if ( ! $output = get_transient( $cache_key ) ) {
    ob_start();
    get_template_part( $template_path, $template_name );
    $output = ob_get_clean();
    set_transient( $cache_key, $output, HOUR_IN_SECONDS );
  }
  echo $output;
}
get_header();
get_template_part( 'partials/fp', 'hero' );
templateCache( 'partials/fp', 'features' );
templateCache( 'partials/fp', 'segment-section' );
templateCache( 'partials/fp', 'products' );
templateCache( 'partials/fp', 'customers' );
templateCache( 'partials/fp', 'blog-section' );
get_template_part( 'partials/fp', 'cta-section' );
get_template_part( 'partials/tech', 'logos-section' );
get_footer();

Resultatet: Tiden sänkt från 450 ms till 143 ms

En ny, manuellt initierad spårning via Tideways bekräftar att optimeringen fungerar som avsett. Siddelarna segment-section och customers som syntes tydligt i den tidigare spårningen har praktiskt taget försvunnit i diagrammet, medan delarna hero och cta-section som vi inte kapslade in i vår cache-kapsling syns.

Observera att dessa båda illustrationer har totalt olika skalning. I det första tidsdiagrammet från Tideways omfattar x-axeln 0–450 millisekunder, medan avståndet mellan höger och vänster sida av diagram nummer två endast är 143 millisekunder.

När vi kör vårt eget testverktyg wp-speed-test direkt på själva servern bekräftar det att PHP-koden för startsidan genereras mycket snabbare än tidigare:

Före:
seravocom@seravocom:~$ wp-speed-test 
Testing speed URL https://seravo.com...

For an explanation of the different times, please see docs at https://curl.haxx.se/docs/manpage.html

URL                  TOTAL NAMELOOKUP CONNECT APPCONNECT PRETRANSFER STARTTRANSFER    = AVG
https://seravo.com   0.405      0.060   0.061      0.064       0.064         0.403    0.405
https://seravo.com   0.380      0.000   0.000      0.000       0.000         0.379    0.392
https://seravo.com   0.313      0.000   0.000      0.000       0.000         0.312    0.366
https://seravo.com   0.330      0.000   0.000      0.000       0.000         0.328    0.357
https://seravo.com   0.340      0.000   0.000      0.000       0.000         0.339    0.353
https://seravo.com   0.331      0.000   0.000      0.000       0.000         0.330    0.350


Efter:
seravocom@seravocom:~$ wp-speed-test 
Testing speed URL https://seravo.com...

For an explanation of the different times, please see docs at https://curl.haxx.se/docs/manpage.html

URL                  TOTAL NAMELOOKUP CONNECT APPCONNECT PRETRANSFER STARTTRANSFER    = AVG
https://seravo.com   0.098      0.004   0.004      0.008       0.008         0.096    0.098
https://seravo.com   0.092      0.000   0.000      0.000       0.000         0.090    0.095
https://seravo.com   0.092      0.000   0.000      0.000       0.000         0.091    0.094
https://seravo.com   0.086      0.000   0.000      0.000       0.000         0.085    0.092
https://seravo.com   0.089      0.000   0.000      0.000       0.000         0.088    0.091
https://seravo.com   0.090      0.000   0.000      0.000       0.000         0.089    0.091

Tack vare Tideways behöver vi inte bara förlita oss på några få manuella mätningar före och efter, utan kan även se på den långsiktiga stickprovshistoriken som Tideways sparar. I detta fall var resultatet verkligen drastiskt:

Historikvyn i Tideways. Notera att användningen av WP-transienter startade runt kl. 16:00.

Använd transienter och en server som använder Redis och objekts-cache

Vi rekommenderar varmt alla utvecklare att börja använda funktionen WordPress-transienter till att optimera sina webbplatser för högre hastighet. För bästa möjliga effekt behöver du köra en servermiljö där transienterna sparas i RAM-minne. Hos Seravo är Redis-servern aktiverad som standard för alla våra kunder vilket ger dem de allra största fördelarna av att använda transienter.

Vill du få artiklar som denna direkt hem till din inkorg? Prenumerera på vårt utvecklarbrev och ligg steget före konkurrenterna med de senaste och bästa knepen, verktygen och tekniska lösningarna för WordPress-utveckling.