SW6 (auch 5) Performance erster Aufruf

I Beschreibung

Wir haben jetzt unseren ersten SW6-Shop auf den Produktionsmodus gesetzt.

Wenn wir jetzt eine Seite des Shops (egal welche) zum ersten Mal aufrufen, beträgt die Ladezeit um die 700 ms - beim zweiten Aufruf ohne Browser-Cache liegt der Aufruf dann bei ca 120-140ms. Auch wenn ich auf zwei komplett unterschiedlichen Geräten dieses Szenario durchführe, ist dieser Effekt zu beobachten. Ich navigiere mit Gerät 1 zur Startseite unseres Shops (700ms Ladezeit) - dann navigiere ich mit einem zweiten Gerät aus einem komplett unabhängigen Netzwerk auf die Startseite und die Seite lädt in 120-140ms. 

Bei SW 5 haben wir das gleiche Verhalten festgestellt - erster Aufruf ca. 600 ms und zweiter Auruf ohne Browser-Cache 30-60ms.

Klickt im Shop dann kein Nutzer für etwa eine halbe Stunde eine gewisse Seite an, so beträgt die Ladezeit dieser Seite wieder 600/700 ms für den nächsten Kunden.

 

Einstellungen:

Shopware 6.2.0

PHP 7.4.7

nginx

OPcache aktiviert

APCu aktiviert

10.3.23-MariaDB

Shopware Http-Cache ist aufgewärmt

 

  1. Kann dieses Verhalten jemand erklären?

  2. Liegt das am APCu, der nach einer gewissen geleert wird?

  3. Liegt es am Opcache, der nach einer gewissen geleert wird?

  4. Liegt es an irgendeinem MariaDB-Cache?

  5. Liegt es an eine nginx-Einstellung?

  6. Liegt es an der realpath_cache_ttl?

 

Hier noch ein Auszug wichtiger PHP-Einstellungen - für den SW6-Shop haben wir PHP 7.4.7 mit nginx im Einsatz:

extension=apcu.so
apc.enabled=1
apc.shm_size=256M
opcache.memory_consumption=512
opcache.max_accelerated_files=25000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=0
realpath_cache_size=4096K
realpath_cache_ttl=600

zusätzliche nginx-Settings:

gzip on;
gzip_disable "MSIE [1-6]\\.(?!.*SV1)";
gzip_proxied any;
gzip_comp_level 5;
gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/bmp image/svg+xml;
gzip_vary on;

location ~* .(js|jpg|jpeg|gif|webp|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|rtf|swf|ico|flv|txt|ttf|woff|woff2|svg)$ {
    etag on;
    expires 365d;
    if_modified_since exact;
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public";
}

 

Bisher haben wir keinen Shopware-Shop gesehen, bei welchem dieses Verhalten nicht so nachgestellt werden kann - selbst bei https://store.shopware.com/ 

Gerne könnt ihr hier auch eure eigenen Erfahrungen teilen, welche Performance-Optimierungen ihr durchgeführt habt.

Eine Erklärung für das oben beschriebene Phänomen wäre klasse - noch besser wäre natürlich eine Lösung, wie die Performance kontinuierlich auf dem Level von 120-140ms Ladezeiten bleibt.

Theoretisch könnte man auch einen Crawler bauen, der alle 15 Minuten die Seiten des Shops besucht - das halte ich aber für ein wenig überzogen und bei Shops mit etlichen Kategorien/Produkten führt das zu einem massiven Overhead - für kleinere Shops sicherlich in Betracht zu ziehen um kontinuierlich eine schnelle Ladezeit gewährleisten zu können.

 

II Weitere Fragen zum Cache:

Wir haben einen Cronjob eingerichtet über den wir alle 12 Stunden den SW6-Cache neu aufbauen:

php /bin/console dal:refresh:index && php /bin/console cache:clear && php /bin/console cache:warmup && php /bin/console http:cache:warm:up
  1. Werden hier auch die Variantenprodukte aufgewärmt?

  2. Was ist der Unterschied zwischen cache:warmup (Symfony) und http:cache:warm:up?

  3. Warum haben Dateien in /var/cache/prod_hbc8004ac21708e18e6f7c39c9a16f3c2/pools/eB2cM3LwVY/0/H teilweise einen lastmodified-Zeitstempel, der in der Zukunft liegt?

  4. Warum befinden sich in /var/cache/ mehrere “prod_” Ordner - manchmal wird nach cache-clear der alte Ordner nicht gelöscht - ist das ein Bug oder bleiben hier nicht geänderte Dateien im alten Cache-Ordner?

Freue mich auf eure Antworten!

2 „Gefällt mir“

Es gibt ein ähnliches Problem allerdings bei einem anderen System (Contao CMS). Hier war die Vermutung zu Symfony in gewissen Hoster-Umgebungen…nicht das System selbst.

Vielleicht hilft das (hier wurde das filesystem als Schuldiger ausgemacht): https://github.com/contao/contao/issues/809#issuecomment-571509691

1 „Gefällt mir“

Danke - werde diesen Ansatz einmal verfolgen und versuchen nachzuvollziehen, ob es wirklich am Filesystem liegt.

Komisch finde ich nur, dass ich bisher keinen Shopware-Shop gefunden habe, bei dem der erste Aufruf nach längerer Inaktivität nicht bei 500ms-1.5s liegt.

Ich habe meine ganzen Sachen zu 90% bei All-Inkl und Ionos liegen und hatte selbst (bei Contao, SW5 oder SW6) nie dieses Verhalten. Es muss hier wohl eine bestimmte Konfiguration vorliegen. Habe mich aber nicht zuuuu tief damit beschäftigt. Mir kam nur deine Fehlerbeschreibung sehr bekannt vor :slight_smile:

@Kahmoonb‍

Werde das mit dem Filesystem auf jeden Fall einmal anschauen.

Hier noch ein Beispiel -  ich rufe folgende URL auf:

https://store.shopware.com/zenit31487954214/labels-badges-individuell-listing-detailseite.html?c=1066

Erster Aufruf:

https://imgur.com/K2edsUu

Zweiter Aufruf:

https://imgur.com/NCP4aJZ

1 „Gefällt mir“

Das macht natürlich Sinn. Gehen wir mal davon aus dass die Seite -IMMER- aus dem Cache geliefert wird. Trotzdem ist der Cache ja trotzdem eine Datei auf dem Filesystem.

Sobald die Datei geholt wird ist sie im RAM des Servers (Filesystem Page Cache). Wenn diese dann längere Zeit nicht mehr geholt wird verschwindet sie aus dem RAM und muss wieder von der Platte geholt werden. (Genaugenommen verschwindet sie wenn genug andere Dateien geholt wurden und diese in den Ram gelegt werden und dadurch der Ram irgendwann mal “voll” ist.)

Könnte man mit entsprechenden Linux Tools wahrscheinlich exakt nachvollziehen.

 

 

1 „Gefällt mir“

Wenn das der Fall wäre, gibt es eine Möglichkeit dem Server zu sagen, dass er die Dateien länger als 10 Minuten im RAM belassen soll, bzw. dass er diese erst entfernt, wenn sie geändert wurden oder der RAM an eine bestimmte Grenze stößt?

Das macht Linux schon von sich aus. Die Dateien werden erst entfernt wenn der Ram voll ist. Wenn du aber bei einem Shared Hosting bist machen ja andere Leute deinen Ram voll. Ist es ein eigener Server kannst ja mit ‚free‘ nachsehen wie voll der Ram gerade ist.

                 total        used        free      shared  buff/cache   available
Mem:       25165824     4420600    17073356     1404216     3671868    20499464
Swap:       1048576           0     1048576

Ich bezweifle, dass er das bei uns erst macht, wenn der RAM voll ist…
 

Jep, das sieht so aus als wäre durchaus noch was frei…

Wenn du herausfinden kannst welche Datei er aus dem Cache holt (evtl. mit fatrace beim Zugriff?) kannst du mittels vmtouch sehen wieviel davon im Cache ist.

Also du brauchst:

  • fatrace um herauszufinden welche Datei zugegriffen wird

  • vmtouch um herauszufinden wieviel der Datei gerade im Cache ist

  • BCC + BPFTrace um mein cooles Programm zu nutzen welches dir die Geschwindigkeit des read Befehls ab dem Zugriff aufs virtuelle Filesystem zeigt

Beispiel die Datei ‚hello.txt‘ mit ihren 12 Bytes:

Raus aus dem Cache:

vmtouch -e hello.txt

Dann mein Programm ./readlat.bt | grep hello.txt, und nun zweimal hintereinander ‚cat‘:

3489       85697  85697  hello.txt 464680
3489       85697  85697  hello.txt    831
6233       85698  85698  hello.txt   4268
6233       85698  85698  hello.txt   1653

-> Der erste Zugriff hat also 464680 Nanosekunden gebraucht

-> Der zweite Zugriff (nun war sie im Cache) hat 4268 Nanosekunden gebraucht.

Was die jeweils Zweite Zeile ist, die ausgegeben ist, weiß ich jetzt auch nicht.

Hier der Code:

#!/usr/local/bin/bpftrace

#include

BEGIN
{
       printf(„Tracing fs read calls(). Ctrl-C to end.\n“);
       printf(„%-10s %-6s %-6s %6s %6s\n“, „TIME(ms)“, „PID“, „TID“, „FILE“, „NS“);
}

kprobe:vfs_read
{
       @start[tid] = nsecs;
       @file[tid] = arg0;
}

kretprobe:vfs_read
/@start[tid]/
{
       $dur = (nsecs - @start[tid]);
       $file = (struct file *)@file[tid];
       $name = $file->f_path.dentry->d_name.name;
       
       printf(„%-10u %-6d %-6d %s %6d\n“, elapsed / 1000000, pid, tid, str($name), $dur);
       delete(@start[tid]);
       delete(@file[tid]);
}

Nerdig genug? Bin auf die Ergebnisse gespannt!

 

1 „Gefällt mir“

Uh! Genau das was man sehen will :slight_smile:

Werde ich morgen testen! Tausend Dank!

Bin aber immer noch am zweifeln ob es daran liegt, da ich bisher wirklich keinen SW5 / SW6 Shop gefunden habe, bei dem es sich nicht so verhält wie beschrieben.

Um das noch nachzureichen: https://stackoverflow.com/questions/60045498/why-does-cat-call-read-twice-when-once-was-enough

Nach etlichen Tests und Anpassungen an den Konfigurationsdateien von PHP, PHP-FPM, nginx, MariaDB ist SW6 jetzt unfassbar schnell.

Hier einmal ein Auszug aus unserer PHP-Konfig - falls es hier etwas zu verbessern gibt gerne Bescheid geben:

apc.shm_size=512M
opcache.memory_consumption=1024
opcache.max_accelerated_files=25000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=0
realpath_cache_size=4096K
realpath_cache_ttl=3600
opcache.interned_strings_buffer=64
opcache.max_file_size=0
opcache.file_cache_only=0

Hier auch die Demo-Shop-URL:

https://eseom-shopware-6-demo.eseom.de/Hauptartikel/SWDEMO10001

Falls euch sonst noch etwas einfällt, wie die Performance gesteigert werden kann, gerne Bescheid geben.

Auch nochmals vielen Dank @ThomasChr‍ für dein Skript.

Ist denn der Effekt das der erste Aufruf deutlich länger dauert und nachfolgende Aufrufe schnell sind, aber nur ca. 30 Minuten lang jetzt weg?

Ja, der Effekt ist jetzt auch weg.

Haben hierzu noch ein Skript geschrieben, dass alle 10 Minuten die URLs der Sitemap.xml besucht. 

Die Ladezeiten liegen jetzt bei 40-80ms.

Ohne das Skript wären die Ladezeiten bei 120-160ms nach 30 Minuten, in denen die Seite nicht besucht wurde.

Das Skript kann man natürlich nur anwenden, wenn wenige Produkte im Shop vorhanden sind oder ein entsprechend starker Server vorhanden ist. 

Hier muss dann die Last beobachtet werden.

Hallo,

also wenn ich die genannte Demoseite aufrufe bzw. teste finde ich die Ladezeit mit 1,1 SEK. nicht "unfassbar schnell …
Oder mache ich beim Testen etwas falsch?

Sind auch gerade am Updates einspielen und weiteren Änderungen vornehmen - kannst es aber gerne noch einmal probieren :slight_smile:

https://imgur.com/TJqAnOw

Imgur

 

Haben unter anderem max_allowed_packet    = 512M in der MariaDB Konfig gesetzt und mussten den Service neustarten und alle neu aufwärmen.

Habe eben nochmals getestet…

Komme jetzt auf 1,2 Sekunden - also sogar eine noch etwas längere Ladezeit - getestet wurde um 12:06 Uhr

Mit welchem Tool testest du denn?

Hast du auf der Seite schon einmal navigiert? Eigentlich spürt man das auch schon, dass es keine Sekunde ist :slight_smile:

Vielen Dank schon einmal, dass du dir das Ganze anschaust.

Getestet wurde mit:

https://www.uptrends.de/tools/website-ladezeit-check