Laravel Cafè #6 - Una Cache Performante

Nel Cafè di oggi, Filippo gioca con una VM e i vari driver cache, fa alcuni esperimenti e ci dice la sua...
francesco
Filippo Galante
18/01/2017 in Tutorial


Benvenuto al Laravel Cafè! Ogni settimana proporremo un nuovo argomento sul mondo Laravel, quindi trova un posto libero, prendi un caffè e condividi le tue opinioni con la comunità! L'idea è di creare un punto di discussione. Se hai qualche perplessità sull'argomento trattato, leggi fino alla fine e fai una domanda usando il forum! Cercheremo di risponderci a vicenda e di aiutarci, ed il confronto ci farà crescere tutti un po' di più.

Di mercoledì in mercoledì parleremo di qualcosa di diverso, quindi tornaci a trovare! Potresti dare una mano a qualcuno in difficoltà, o ricevere tu un aiuto in caso di problemi! Dai, siediti, il primo caffè lo offriamo noi.

L'Argomento

Nei giorni scorsi ho fatto una mia personale pausa caffè leggendo questo articolo il quale mi ha dato diversi spunti interessanti per questo Laravel Cafè. Oggi metteremo alla prova Laravel, cercando di capire come si comportano i diversi driver per la Cache messi a disposizione dal framework. Salto l'introduzione sulla configurazione e utilizzo della Cache rimandandoti direttamente alla documentazione ufficiale per concentrarmi sull'ambiente utilizzato, il test e i suoi risultati.

A differenza del test che effettua l'autore dell'articolo originale, ho utilizzato in primo luogo una macchina virtuale molto simile ad un ambiente di produzione che può essere messo a disposizone da un qualunque provider VPS e la base dati usata è decisamente più corposa rispetto all'originale.

Ambiente

Partiamo dal dietro le quinte del dietro le quinte: una macchina virtuale su cui è installato Ubuntu Server e di seguito sono elencati i dettagli della macchina. Un piccolo appunto, la vm è collegata all'interno di una rete locale con il mio computer, quindi tutti i possibili ritardi dovuti alla rete dovrebbero essere assolutamente irrisori, magari in un futurò berremo un caffè eseguendo i test su una macchina remota!

Software di virtualizzazione: Oracle VM Virtualbox

  • Macchina virtuale linux - Ubuntu 16.04.1 LTS x64
  • Hard disk: hd vdi da 20GB
  • Timing cached reads: 38426 MB in 2.00 seconds = 19242.88 MB/sec
  • Timing buffered disk reads: 1216 MB in 3.00 seconds = 405.21 MB/sec
  • CPU: 1 CPU
  • RAM: 4000 MB

Software aggiuntivi

Per quanto riguarda l'applicazione in Laravel che elaborerà il test, ho configurato un'installazione standard di Laravel 5.3, con l'aggiunta dei packages strettamente necessari al test.

Il Codice

Prima di vedere il dettaglio del codice dell'applicazione di test vorrei fare una breve premessa. Anche se l'articolo originale utilizza postman per effettuare i test, io ho preferito farmi uno script molto semplice che utilizza curl per due motivi:

  1. curl usato nativamente lo ritengo più preciso di Postman.
  2. Sopra i 100.000 risultati Postman va in crash probabilmente a causa del peso del json in response.

Il test effettuato si basa solo sul tempo di risposta dell'applicazione dal momento in cui viene effettuata la chiamata http al momento in cui viene ricevuto interamente il response. Come anticipato è utilizzata una base di dati fake sia per richiamare il metodo Cache::get(...) che per il metodo Cache::tags(...)->get(...); (quest'ultimo solo per Memcached e Redis dato che sono gli unici driver a supportare i tag). La tabella utilizzata per il test contiene un milione di record e da PHPMyAdmin risulta pesare 1.1GB.

Vediamo quindi la parte di codice implementato. Ho creato un modello Articles e corrispettiva migrazione:

// Migrazione
Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title', 100);
    $table->string('slug', 100);
    $table->text('body');
    $table->timestamps();
});

// Model
namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = true;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['title', 'slug', 'body'];

}

Per popolare i dati fake ho utilizzato una model factory e relativo seeder. Quest'ultimo è stato limitato alla creazione di 100.000 record alla volta e nonostante abbia provato diverse strade, questo è un limite che non sono riuscito a superare senza che il processo andasse in crash:

// database/factories/ModelFactory.php
$factory->define(App\Article::class, function (Faker\Generator $faker) {
    return [
        'title' => $faker->realText($faker->numberBetween(50, 100)),
        'slug' => $faker->slug,
        'body' => $faker->realText(10000),
    ];
});

// database/seeds/ArticlesTableSeeder
use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Article::class, 100000)->create();
    }

}

Per semplicità e velocità non ho creato alcun controller, ma delle route con relativa callback per caricare i dati dal database e dalla cache (con e senza tag) e restituire un response in JSON. Come si nota dal codice, ciascuna route ha un parametro count che determina il range di valori da caricare.

Route::get('/test/{count}/db', function ($count) {
    $articles = App\Article::limit($count)->get();
    return response()->json($articles);
});

Route::get('/test/{count}/cache', function ($count) {
    $articles = Cache::get('articles_' . $count, function() use ($count) {
                return App\Article::limit($count)->get();
            });

    return response()->json($articles);
});

Route::get('/test/{count}/tags', function ($count) {
    $articles = Cache::tags(['articles'])->get('articles_' . $count, function() use ($count) {
        return App\Article::limit($count)->get();
    });

    return response()->json($articles);
});

curl

Passiamo quindi ai risultati ricordandoci che per i driver si parte sempre con la cache vuota e di conseguenza la prima chiamata recuperare i dati e successivamente popola la cache. La struttura del test è ad ogni modo molto semplice:

  • 5 chiamate http da 10, 100, 1000, 10.000, 100.000 e 1.000.000 di risultati che restituiscono i dati dal database
  • 5 chiamate http per ciascun driver da 10, 100, 1000, 10.000, 100.000 e 1.000.000 di risultati che restituiscono i dati contenuti nella cache

TEST 1: recupero dati da database

  • 1° chiamata

    • 10: 62 ms
    • 100: 26 ms
    • 1000: 57 ms
    • 10000: 938 ms
    • 100000: 5104 ms
    • 100000: 12717 ms
  • 2° chiamata

    • 10: 61 ms
    • 100: 28 ms
    • 1000: 56 ms
    • 10000: 1025 ms
    • 100000: 4690 ms
    • 100000: 12586 ms
  • 3° chiamata

    • 10: 15 ms
    • 100: 31 ms
    • 1000: 47 ms
    • 10000: 933 ms
    • 100000: 4690 ms
    • 100000: 14601 ms
  • 4° chiamata

    • 10: 11 ms
    • 100: 28 ms
    • 1000: 49 ms
    • 10000: 700 ms
    • 100000: 4709 ms
    • 100000: 13327 ms
  • 5° chiamata

    • 10: 15 ms
    • 100: 27 ms
    • 1000: 130 ms
    • 10000: 481 ms
    • 100000: 5081 ms
    • 100000: 18040 ms

media

  • 10: 32,8 ms
  • 100: 28 ms
  • 1000: 67,8 ms
  • 10000: 815,4 ms
  • 100000: 4854,8 ms
  • 1000000: 14254,2 ms

  • 1° chiamata

    • 10: 317 ms
    • 100: 202 ms
    • 1000: 181 ms
    • 10000: 1827 ms
    • 100000: 13057 ms
    • 100000: 16193 ms
  • 2° chiamata

    • 10: 87 ms
    • 100: 194 ms
    • 1000: 168 ms
    • 10000: 1505 ms
    • 100000: 10531 ms
    • 100000: 14374 ms
  • 3° chiamata

    • 10: 70 ms
    • 100: 94 ms
    • 1000: 167 ms
    • 10000: 1043 ms
    • 100000: 10561 ms
    • 100000: 14834 ms
  • 4° chiamata

    • 10: 63 ms
    • 100: 45 ms
    • 1000: 169 ms
    • 10000: 1414 ms
    • 100000: 11587 ms
    • 100000: 15879 ms
  • 5° chiamata

    • 10: 107 ms
    • 100: 32 ms
    • 1000: 167 ms
    • 10000: 1339 ms
    • 100000: 12080 ms
    • 100000: 16678 ms

media

  • 10: 128,8 ms
  • 100: 113,4 ms
  • 1000: 170,4 ms
  • 10000: 1425,6 ms
  • 100000: 11563,2 ms
  • 1000000: 15591,6 ms

TEST 2: file driver

  • 1° chiamata

    • 10: 48 ms
    • 100: 25 ms
    • 1000: 48 ms
    • 10000: 416 ms
    • 100000: 4449 ms
    • 100000: 10622 ms
  • 2° chiamata

    • 10: 8 ms
    • 100: 10 ms
    • 1000: 41 ms
    • 10000: 417 ms
    • 100000: 4960 ms
    • 100000: 13674 ms
  • 3° chiamata

    • 10: 12 ms
    • 100: 17 ms
    • 1000: 46 ms
    • 10000: 413 ms
    • 100000: 4676 ms
    • 100000: 12682 ms
  • 4° chiamata

    • 10: 9 ms
    • 100: 15 ms
    • 1000: 43 ms
    • 10000: 435 ms
    • 100000: 4722 ms
    • 100000: 14586 ms
  • 5° chiamata

    • 10: 13 ms
    • 100: 8 ms
    • 1000: 41 ms
    • 10000: 416 ms
    • 100000: 4727 ms
    • 100000: 21205 ms

media

  • 10: 18 ms
  • 100: 15 ms
  • 1000: 43,8 ms
  • 10000: 419,4 ms
  • 100000: 4706,8 ms
  • 1000000: 14553,8 ms

  • 1° chiamata

    • 10: 396 ms
    • 100: 343 ms
    • 1000: 222 ms
    • 10000: 1568 ms
    • 100000: 15365 ms
    • 100000: 16403 ms
  • 2° chiamata

    • 10: 228 ms
    • 100: 204 ms
    • 1000: 234 ms
    • 10000: 1432 ms
    • 100000: 11894 ms
    • 100000: 16597 ms
  • 3° chiamata

    • 10: 193 ms
    • 100: 58 ms
    • 1000: 136 ms
    • 10000: 1745 ms
    • 100000: 11666 ms
    • 100000: 15965 ms
  • 4° chiamata

    • 10: 117 ms
    • 100: 22 ms
    • 1000: 219 ms
    • 10000: 1483 ms
    • 100000: 10461 ms
    • 100000: 15386 ms
  • 5° chiamata

    • 10: 400 ms
    • 100: 28 ms
    • 1000: 144 ms
    • 10000: 1696 ms
    • 100000: 10414 ms
    • 100000: 16459 ms

media

  • 10: 266,8 ms
  • 100: 131 ms
  • 1000: 191 ms
  • 10000: 1584,8 ms
  • 100000: 11960 ms
  • 1000000: 16162 ms

TEST 3: array driver

  • 1° chiamata

    • 10: 315 ms
    • 100: 262 ms
    • 1000: 433 ms
    • 10000: 8109 ms
    • 100000: 4449 ms
    • 100000: memoria esaurita
  • 2° chiamata

    • 10: 45 ms
    • 100: 50 ms
    • 1000: 1143 ms
    • 10000: 7777 ms
    • 100000: 4960 ms
    • 100000: memoria esaurita
  • 3° chiamata

    • 10: 43 ms
    • 100: 43 ms
    • 1000: 1089 ms
    • 10000: 4770 ms
    • 100000: 4676 ms
    • 100000: memoria esaurita
  • 4° chiamata

    • 10: 34 ms
    • 100: 33 ms
    • 1000: 986 ms
    • 10000: 4745 ms
    • 100000: 4722 ms
    • 100000: memoria esaurita
  • 5° chiamata

    • 10: 33 ms
    • 100: 27 ms
    • 1000: 927 ms
    • 10000: 4861 ms
    • 100000: 4727 ms
    • 100000: memoria esaurita

media

  • 10: 94 ms
  • 100: 83 ms
  • 1000: 915,6 ms
  • 10000: 6052,4 ms
  • 100000: 4706,8 ms
  • 1000000: ---

  • 1° chiamata

    • 10: 154 ms
    • 100: 180 ms
    • 1000: 701 ms
    • 10000: 3987 ms
    • 100000: 13867 ms
    • 100000: memoria esaurita
  • 2° chiamata

    • 10: 68 ms
    • 100: 32 ms
    • 1000: 128 ms
    • 10000: 1648 ms
    • 100000: 10810 ms
    • 100000: memoria esaurita
  • 3° chiamata

    • 10: 52 ms
    • 100: 35 ms
    • 1000: 222 ms
    • 10000: 1041 ms
    • 100000: 11431 ms
    • 100000: memoria esaurita
  • 4° chiamata

    • 10: 87 ms
    • 100: 29 ms
    • 1000: 229 ms
    • 10000: 1587 ms
    • 100000: 19202 ms
    • 100000: memoria esaurita
  • 5° chiamata

    • 10: 54 ms
    • 100: 41 ms
    • 1000: 206 ms
    • 10000: 1637 ms
    • 100000: 11698 ms
    • 100000: memoria esaurita

media

  • 10: 83 ms
  • 100: 63,4 ms
  • 1000: 297,2 ms
  • 10000: 1980 ms
  • 100000: 13401,6 ms
  • 1000000: ---

TEST 4: database driver

  • 1° chiamata

    • 10: 92 ms
    • 100: 19 ms
    • 1000: 56 ms
    • 10000: 412 ms
    • 100000: 4696 ms
    • 100000: memoria esaurita
  • 2° chiamata

    • 10: 17 ms
    • 100: 17 ms
    • 1000: 58 ms
    • 10000: 428 ms
    • 100000: 4107 ms
    • 100000: memoria esaurita
  • 3° chiamata

    • 10: 21 ms
    • 100: 18 ms
    • 1000: 60 ms
    • 10000: 414 ms
    • 100000: 4687 ms
    • 100000: memoria esaurita
  • 4° chiamata

    • 10: 20 ms
    • 100: 20 ms
    • 1000: 59 ms
    • 10000: 416 ms
    • 100000: 4707 ms
    • 100000: memoria esaurita
  • 5° chiamata

    • 10: 22 ms
    • 100: 18 ms
    • 1000: 58 ms
    • 10000: 424 ms
    • 100000: 4730 ms
    • 100000: memoria esaurita

media

  • 10: 34,4 ms
  • 100: 18,4 ms
  • 1000: 58,2 ms
  • 10000: 418,8 ms
  • 100000: 4585,4 ms
  • 1000000: ---

  • 1° chiamata

    • 10: 35 ms
    • 100: 38 ms
    • 1000: 149 ms
    • 10000: 2164 ms
    • 100000: 13251 ms
    • 100000: memoria esaurita
  • 2° chiamata

    • 10: 22 ms
    • 100: 26 ms
    • 1000: 198 ms
    • 10000: 1130 ms
    • 100000: 11363 ms
    • 100000: memoria esaurita
  • 3° chiamata

    • 10: 21 ms
    • 100: 38 ms
    • 1000: 113 ms
    • 10000: 1386 ms
    • 100000: 10897 ms
    • 100000: memoria esaurita ms
  • 4° chiamata

    • 10: 27 ms
    • 100: 33 ms
    • 1000: 201 ms
    • 10000: 1035 ms
    • 100000: 10349 ms
    • 100000: memoria esaurita
  • 5° chiamata

    • 10: 21 ms
    • 100: 39 ms
    • 1000: 115 ms
    • 10000: 1585 ms
    • 100000: 10326 ms
    • 100000: memoria esaurita

media

  • 10: 25,2 ms
  • 100: 34,8 ms
  • 1000: 155,2 ms
  • 10000: 1460 ms ms
  • 100000: 11237,2 ms
  • 1000000: ---

TEST 5a: memcached driver

  • 1° chiamata

    • 10: 78 ms
    • 100: 17 ms
    • 1000: 55 ms
    • 10000: 422 ms
    • 100000: 4703 ms
    • 100000: 8257 ms
  • 2° chiamata

    • 10: 18 ms
    • 100: 18 ms
    • 1000: 57 ms
    • 10000: 420 ms
    • 100000: 4668 ms
    • 100000: 9378 ms
  • 3° chiamata

    • 10: 19 ms
    • 100: 23 ms
    • 1000: 57 ms
    • 10000: 413 ms
    • 100000: 4691 ms
    • 100000: 9270 ms
  • 4° chiamata

    • 10: 20 ms
    • 100: 19 ms
    • 1000: 54 ms
    • 10000: 423 ms
    • 100000: 4713 ms
    • 100000: 8522 ms
  • 5° chiamata

    • 10: 9 ms
    • 100: 21 ms
    • 1000: 57 ms
    • 10000: 425 ms
    • 100000: 4720 ms
    • 100000: 8691 ms

media

  • 10: 28,8 ms
  • 100: 19,6 ms
  • 1000: 56 ms
  • 10000: 420,6 ms
  • 100000: 4699 ms
  • 1000000: 8823,6 ms

  • 1° chiamata

    • 10: 350 ms
    • 100: 350 ms
    • 1000: 168 ms
    • 10000: 1489 ms
    • 100000: 13345 ms
    • 100000: 10360 ms
  • 2° chiamata

    • 10: 120 ms
    • 100: 287 ms
    • 1000: 162 ms
    • 10000: 1555 ms
    • 100000: 14447 ms
    • 100000: 10391 ms
  • 3° chiamata

    • 10: 95 ms
    • 100: 55 ms
    • 1000: 173 ms
    • 10000: 1469 ms
    • 100000: 13944 ms
    • 100000: 11183 ms
  • 4° chiamata

    • 10: 102 ms
    • 100: 37 ms
    • 1000: 189 ms
    • 10000: 1498 ms
    • 100000: 9950 ms
    • 100000: 11584 ms
  • 5° chiamata

    • 10: 109 ms
    • 100: 37 ms
    • 1000: 172 ms
    • 10000: 1478 ms
    • 100000: 10378 ms
    • 100000: 11608 ms

media

  • 10: 155,2 ms
  • 100: 153,2 ms
  • 1000: 172,8 ms
  • 10000: 1497,8 ms
  • 100000: 12412,8 ms
  • 1000000: 11025,2 ms

TEST 5b: memcached driver con tags

  • 1° chiamata

    • 10: 76 ms
    • 100: 27 ms
    • 1000: 111 ms
    • 10000: 1510 ms
    • 100000: 10306 ms
    • 100000: 10304 ms
  • 2° chiamata

    • 10: 56 ms
    • 100: 29 ms
    • 1000: 115 ms
    • 10000: 1037 ms
    • 100000: 10306 ms
    • 100000: 10343 ms
  • 3° chiamata

    • 10: 20 ms
    • 100: 22 ms
    • 1000: 124 ms
    • 10000: 1037 ms
    • 100000: 10306 ms
    • 100000: 10342 ms
  • 4° chiamata

    • 10: 21 ms
    • 100: 26 ms
    • 1000: 114 ms
    • 10000: 1026 ms
    • 100000: 10300 ms
    • 100000: 9810 ms
  • 5° chiamata

    • 10: 13 ms
    • 100: 27 ms
    • 1000: 110 ms
    • 10000: 1023 ms
    • 100000: 10309 ms
    • 100000: 10606 ms

media

  • 10: 37,2 ms
  • 100: 26,2 ms
  • 1000: 114,8 ms
  • 10000: 1126,6 ms
  • 100000: 10305,4 ms
  • 1000000: 10281 ms

  • 1° chiamata

    • 10: 25 ms
    • 100: 27 ms
    • 1000: 111 ms
    • 10000: 1028 ms
    • 100000: 10597 ms
    • 100000: 10328 ms
  • 2° chiamata

    • 10: 13 ms
    • 100: 25 ms
    • 1000: 118 ms
    • 10000: 1037 ms
    • 100000: 10326 ms
    • 100000: 10341 ms
  • 3° chiamata

    • 10: 17 ms
    • 100: 30 ms
    • 1000: 116 ms
    • 10000: 1039 ms
    • 100000: 10597 ms
    • 100000: 10395 ms
  • 4° chiamata

    • 10: 14 ms
    • 100: 26 ms
    • 1000: 117 ms
    • 10000: 1024 ms
    • 100000: 10597 ms
    • 100000: 10042 ms
  • 5° chiamata

    • 10: 20 ms
    • 100: 26 ms
    • 1000: 115 ms
    • 10000: 1041 ms
    • 100000: 10597 ms
    • 100000: 13035 ms

media

  • 10: 17,8 ms
  • 100: 26,8 ms
  • 1000: 115,4 ms
  • 10000: 1033,8 ms
  • 100000: 10542,8 ms
  • 1000000: 10828,2 ms

TEST 6a: redis driver

  • 1° chiamata

    • 10: 158 ms
    • 100: 33 ms
    • 1000: 59 ms
    • 10000: 420 ms
    • 100000: 4067 ms
    • 100000: 8423 ms
  • 2° chiamata

    • 10: 27 ms
    • 100: 26 ms
    • 1000: 55 ms
    • 10000: 418 ms
    • 100000: 4690 ms
    • 100000: 8406 ms
  • 3° chiamata

    • 10: 19 ms
    • 100: 21 ms
    • 1000: 51 ms
    • 10000: 426 ms
    • 100000: 4909 ms
    • 100000: 8525 ms
  • 4° chiamata

    • 10: 20 ms
    • 100: 20 ms
    • 1000: 57 ms
    • 10000: 410 ms
    • 100000: 4929 ms
    • 100000: 8433 ms
  • 5° chiamata

    • 10: 30 ms
    • 100: 20 ms
    • 1000: 59 ms
    • 10000: 424 ms
    • 100000: 4909 ms
    • 100000: 8456 ms

media

  • 10: 50,8 ms
  • 100: 24 ms
  • 1000: 56,2 ms
  • 10000: 419,6 ms
  • 100000: 4700,8 ms
  • 1000000: 8448,6 ms

  • 1° chiamata

    • 10: 366 ms
    • 100: 359 ms
    • 1000: 198 ms
    • 10000: 1970 ms
    • 100000: 17443 ms
    • 100000: 10398 ms
  • 2° chiamata

    • 10: 151 ms
    • 100: 38 ms
    • 1000: 188 ms
    • 10000: 1526 ms
    • 100000: 9892 ms
    • 100000: 11747 ms
  • 3° chiamata

    • 10: 165 ms
    • 100: 43 ms
    • 1000: 205 ms
    • 10000: 1483 ms
    • 100000: 10385 ms
    • 100000: 10437 ms
  • 4° chiamata

    • 10: 143 ms
    • 100: 42 ms
    • 1000: 206 ms
    • 10000: 1555 ms
    • 100000: 10402 ms
    • 100000: 9767 ms
  • 5° chiamata

    • 10: 129 ms
    • 100: 37 ms
    • 1000: 191 ms
    • 10000: 1548 ms
    • 100000: 10425 ms
    • 100000: 10380 ms

media

  • 10: 190,8 ms
  • 100: 103,8 ms
  • 1000: 197,6 ms
  • 10000: 1616,4 ms
  • 100000: 11709,4 ms
  • 1000000: 10545,8 ms

TEST 6b: redis driver con tags

  • 1° chiamata

    • 10: 60 ms
    • 100: 25 ms
    • 1000: 104 ms
    • 10000: 1035 ms
    • 100000: 10353 ms
    • 100000: 10360 ms
  • 2° chiamata

    • 10: 16 ms
    • 100: 26 ms
    • 1000: 110 ms
    • 10000: 1041 ms
    • 100000: 10335 ms
    • 100000: 9832 ms
  • 3° chiamata

    • 10: 14 ms
    • 100: 24 ms
    • 1000: 107 ms
    • 10000: 1042 ms
    • 100000: 10344 ms
    • 100000: 10347 ms
  • 4° chiamata

    • 10: 14 ms
    • 100: 22 ms
    • 1000: 109 ms
    • 10000: 1042 ms
    • 100000: 10340 ms
    • 100000: 10372 ms
  • 5° chiamata

    • 10: 11 ms
    • 100: 22 ms
    • 1000: 108 ms
    • 10000: 1031 ms
    • 100000: 10356 ms
    • 100000: 10363 ms

media

  • 10: 23 ms
  • 100: 23,8 ms
  • 1000: 107,6 ms
  • 10000: 1038,2 ms
  • 100000: 10345,6 ms
  • 1000000: 10254,8 ms

  • 1° chiamata

    • 10: 23 ms
    • 100: 22 ms
    • 1000: 110 ms
    • 10000: 1029 ms
    • 100000: 10334 ms
    • 100000: 10361 ms
  • 2° chiamata

    • 10: 14 ms
    • 100: 22 ms
    • 1000: 116 ms
    • 10000: 1038 ms
    • 100000: 10315 ms
    • 100000: 10355 ms
  • 3° chiamata

    • 10: 12 ms
    • 100: 21 ms
    • 1000: 114 ms
    • 10000: 1022 ms
    • 100000: 10328 ms
    • 100000: 10335 ms
  • 4° chiamata

    • 10: 11 ms
    • 100: 22 ms
    • 1000: 119 ms
    • 10000: 1041 ms
    • 100000: 10556 ms
    • 100000: 10342 ms
  • 5° chiamata

    • 10: 10 ms
    • 100: 22 ms
    • 1000: 115 ms
    • 10000: 1039 ms
    • 100000: 9779 ms
    • 100000: 1661035178 ms

media

  • 10: 14 ms
  • 100: 21,8 ms
  • 1000: 114,8 ms
  • 10000: 1033,8 ms
  • 100000: 10262,4 ms
  • 1000000: 10348,8 ms

Diamo un piccolo sguardo ai risultati... A grande sorpresa il driver database risulta essere il più performante come media di recupero dei risultati, anche se devo dire che le impostazioni di MySql sono state aumentate (e non di poco) per evitare crash. Come si nota il driver esaurisce la memoria a disposizione sopra i 100.000 risultati, ma con le configurazioni base già sopra i 1000 risultati o il processo si rallenta esponenzialmente o lancia una exception. Più o meno lo stesso discorso vale per il driver array.

Memcached e Redis, con il supporto dei tags, risultano essere estremamente efficenti sia per applicazioni base che per applicazioni con cache molto "ingombranti" e se guardiamo nel dettaglio i risultati, anche le differenze di tempo di risposta tra un risultato e l'altro sono minime.

Il driver file risulta essere invece molto efficace su cache di piccole dimensioni, e conseguentemente, sicuramente il più indicato nella maggior parte dei casi.

Prima di tirare le conclusioni vorrei sottolineare il fatto che con vm "entry level" i driver database e array risultato essere assolutamente inutili su cache di grandi dimensioni, poiché senza aumentare la memoria a disposizione di PHP o MySQL la nostra applicazione non lancia esclusivamente una FatalErrorException: memory exhausted.

Il podio del test è quindi il seguente:

  1. Database (fino ai 100.000 risultati)
  2. Redis (oltre 100.000 risultati e utilizzando i tags)
  3. Memcached (oltre 100.000 risultati e utilizzando i tags)

In verità secondo me il podio vede al primo posto parimerito Redis e Memcached per la facilità di implementazione e le performance, il driver file al secondo posto e il driver database al terzo anche se la poca malleabilità di quest'ultimo su grossi quantitativi di dati potrebbe essere molto limitativo se al posto di semplici collezioni recuperate dal database si inizia a prendere in considerazione immagini o oggetti più complessi.

... ed ora?

E Voi?

Quale è il driver che più utilizzate? Come gestite il sistema di Cache nelle vostre applicazioni? Avete effettuato test simili utilizzando ambiente di produzione differenti?

Raggiungeteci sui vari canali di Laravel-Italia, sul forum, su Slack e dite la vostra!