WordPress-sivut 300% nopeammaksi transienteilla

Tiesitkö, että WordPress pitää sisällään oman välimuistijärjestelmänsä, jota kutsutaan transienteiksi? Transientit ovat helppokäyttöisiä ja oikein käytettyinä todella tehokkaita. Tässä artikkelissa käyn läpi kuinka hyödynsimme WordPressin Transients API:a oman Seravo.com-sivustomme etusivulla ja saavutimme keskimäärin 300% nopeammat sivunlataukset.

Välimuistituksen toteuttaminen on joskus haastavaa, sillä sen oikean keston sekä välimuistin tyhjentämisen ja korvaamisen tarpeen määrittäminen vaatii kehittäjältä vahvaa ymmärrystä koko sivustosta. Se on kuitenkin vaivansa arvoista, sillä jos et hyödynnä välimuistia ja transientien tarjoamia mahdollisuuksia, heität hukkaan potentiaalisesti valtavan nopeushyödyn sivustollasi.

WordPressin Transient API: set_, get_ tai delete_transient()

WordPressin Transients API on rakenteeltaan hyvin yksinkertainen, sillä se koostuu vain kolmesta funktiosta: set, get ja delete. Set-funktiolla määrität mitä välimuistiin talletetaan, get-funktiolla voit hakea sinne tallennetut tiedot ja delete-funktiolla voit tyhjentää välimuistiin tallennettuja asioita ennen niiden luontaista vanhenemista.

Set-funktiolla on kolme käytettävää parametriä: välimuistin nimi (’cache key’), kyseiseen välimuistiin talletettavat arvot/sisällöt, sekä välimuistin vanheneminen sekunneissa. Get-funktio on vieläkin yksinkertaisempi, sillä ainoa määriteltävä parametri on välimuistin nimi eli ’cache key’. Get-funktio palauttaa kyseisestä välimuistista sen sisältämät arvot/sisällöt, tai arvon ’false’, mikäli välimuistista ei löydy mitään.

Transienteja voi hyödyntää esimerkiksi tietokantakyselyiden välimuistittamiseen, kuten alla olevassa WordPress-dokumentaation klassikkoesimerkissä tehdään. Tämän ansiosta mahdollisesti hyvinkin raskaat tietokantakyselyt eivät kuormita sivuston tietokantaa jatkuvasti, vaan pystyy toimittamaan vastauksia kyselyihin välimuistista.

<?php
// Check for transient. If none, then execute WP_Query
if ( false === ( $featured = get_transient( 'foo_featured_posts' ) ) ) {
      $featured = new WP_Query(
	   array(
		'category' => 'featured',
		'posts_per_page' => 5
	   ));
	// Put the results in a transient. Expire after 12 hours.
	set_transient( 'foo_featured_posts', $featured, 12 * HOUR_IN_SECONDS );
} ?>

Mitä transienteihin kannattaa tallentaa?

Kaikki raskaat kyselyt sekä prosessit, joiden vastaus pysyy samana ainakin vähän aikaa, kannattaa tallentaa välimuistiin.

Case: Seravo.comin etusivu

On kaksi suositeltavaa tapaa tutkia mitä PHP-koodissa tapahtuu kun WordPress-sivusto suorittaa sivulatauksen: XDebug ja Tideways, joista jälkimmäinen on oikea vaihtoehto tuotannossa olevilla sivustoilla. Tidewaysin avulla toteutettu seuranta esitti Seravo.com etusivun eri osien suoritusajat allaolevassa vesiputouskaaviossa, jolloin syylliseksi hitauteen paljastui sivupohja, joka haki tietokannasta useita mukautettuja sisältötyyppejä.

Alla on osa kyseisen frontpage.php -sivupohjan sisältöä, joka latasi boilerplate-koodista koostuvia sivupohjan osia, sekä ajoi mukautettuja sisältötyyppejä hakevia silmukoita jokaisella sivulatauksella. Kuten Tideways-profilointi paljasti, näiden sivupohjan osien hakeminen oli suhteellisen raskas operaatio tietokannalle. Sivustojen etusivut harvoin muuttuvat jatkuvasti ja sama pätee myös Seravo.comin etusivuun. Sivun ainoan säännöllisesti päivittyvän osion ollessa uusimmat blogiartikkelit esittelevä osio, se soveltui erinomaisesti välimuistitettavaksi.

<?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();

Toteutimme välimuistittamisen wrapper-funktion avulla, joka hakee kyseisen sivupohjan osan tietokantakyselyllä ainoastaan siinä tapauksessa, että välimuisti on tyhjä. Alla oleva koodinpätkä joko luo sivupohjan osiot tai hakee ne välimuistista, tallentaa ne PHP:n puskuriin ja tulostaa valmiin sivun käyttäjälle.

<?php
/*
 * Wrapper for get_template_part to get the ready-rendered
 * template from the WP Transient cache is exists.
 *
 * Note! This should be only used for static pages that always
 * have the same contents, or at least can be so for an hour
 * (which is the current cache expiry time).
 */
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();

Tulos: latausnopeus 450 millisekunnista 143 millisekuntiin 

Uusi Tideways-seuranta vahvisti lähestymistavan toimivuuden. Aiemmassa mittauksessa erityistä huomiota herättäneet osiot segment-section sekä customers ovat käytännössä kadonneet, kun taas välimuistituksen ulkopuolelle jätetyt hero ja cta-section ovat edelleen selvästi näkyvissä

Huomaa ero kuvien skaalassa: ensimmäisessä Tidewaysin vesiputouskaaviossa skaala on 0-450 ms, kun taas jälkimmäisessä matka vasemmasta reunasta oikeaan reunaan on vain 143 ms.

Ajamalla palvelimella komentoriviltä wp-speed-test -työkaluamme saimme vahvistuksen etusivun PHP:n parantuneesta latausnopeudesta:

Before:
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
After:
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

Tidewaysin ansiosta meidän ei tarvitse luottaa kouralliseen käsipelillä tehtyihin mittaustuloksiin, vaan voimme todeta tekemämme muutosten hyödyn avaamalla Tidewaysin historianäkymän. Tässä tapauksessa tulokset olivat suorastaan häkellyttävät:

Suositus: hyödynnä transienteja ja ota Redis ja object cache käyttöön palvelimellasi

Suosittelemme lämpimästi transienteja kaikille WordPress-sivustojen kehittäjille jotka haluavat optimoida sivustojensa latausnopeuksia. Parhaan tuloksen saavuttamiseksi kannattaa käyttää palvelinympäristöä, jossa transientit säilytetään käyttömuistissa. Seravon WP-palvelussa on oletuksena Redis käytössä kaikille asiakkaille, jolloin transientien tarjoama hyöty on maksimaalinen.