Wo ist der Flaschenhals in miener Seite
Jörg
- webdesign
Hallo,
ich habe eine Seite, die bis zu ihrem Erscheinen auf meinem Bildschirm recht lange braucht.
Ich habe zu begin und zum Ewnde der Seite eine Zeitmessung gesetzt und durch die Differenz der Beiden ermittle ich die gesamte Zeit der Seite.
Seltsamerweise braucht sie aber immer recht lange, wobei manchmal über 6 Sekunden gemessen wird und manchmal nur 0,20 Sekunden.
Dieses seltsame Verhaölren macht es m ir recht schwer, den Flaschenhals dieser Seite zu finden. Es mag an den Tabellen und Indices der hier betroffenen mysql-db liegen, es kann im php verborgen sein. Es sind aber zu viele Codezeilen, um jede Query oder ´jede php-Anweisung einzeln zu hinterfragen, bevor ich mich nicht in Richtung der Codepassage angenähert habe, die hier so stockt.
Könnt Ihr mir Tips geben, wie ich hier vorgehen kann? (insb., da die Seite in ihren Messreihen so große Unterschiede macht und die Seite dennoch meist lange benötigt)
Jörg
Hello,
der Flaschenhals steckt 1000%ig dort, wohin Du uns nicht gucken lässt.
Ohne Input keine Tipps :-(
Glück Auf
Tom vom Berg
Hallo Jörg,
was Du möchtest, ist profiling. Leider ist das in PHP nicht eingebaut.
Lösung 1: Profiling "von Hand".
Dafür verteilst Du an strategischen Stellen Funktionsaufrufe über den Code. Sowas wie profile_mark("Open DB")
oder ein Pärchen wie
$time = profile_begin("Fetch User");
// do work
profile_end("Fetch User", $time);
Und diese Funktionen schreiben einen Timestamp und den Text in eine Logdatei. Die wertest Du nachher aus. profile_end würde noch die Zeitdifferenz zwischen aktueller Zeit und $time loggen.
Wenn Du kein Profiling machst, kommentierst Du die Funktionsinhalte aus. Oder Du verwendest zwei verschiedene Include-Dateien: die eine included Dummys, die andere den echten Kram.
Vorteil:
Nachteil:
Lösung 2: Einsatz eines echten Profilers
Den muss man nur erstmal auf den Server bekommen - wenn Du das nicht darfst, hat sich diese Variante erledigt.
https://stackoverflow.com/questions/21133/simplest-way-to-profile-a-php-script
Hier wird vorgeschlagen, man könnte das mit xdebug machen.
Sucht man im PHP Handbuch nach "profiling", findet man an dieser Stelle den Hinweis auf die PECL-Erweiterung XHProf (PECL, GitHub), die für PHP 7 und PHP 8 verfügbar ist.
Ich hab's noch nie benutzt, ich weiß nicht, wie gut man das auf gehosteten Webspace bekommt. Good Luck 😉
Vorteil:
Nachteil:
Rolf
Hello,
[...]
und man könnte diese Funktion standardmäßig in die Module einbauen und nur aktivieren, wenn ein dafür eigenes Debug-Flag gesetzt ist. Eventuell sollte man auch unterschiedliche Flags für unterschiedliche Funktionsgruppen vorsehen. (MVC, Router-Hierarchie, ...)
Glück Auf
Tom vom Berg
Hallo Rolf,
was Du möchtest, ist profiling. Leider ist das in PHP nicht eingebaut.
Lösung 1: Profiling "von Hand".
Ja, so könnte ichs machen.
Nachteil:
- Viel Arbeit beim Verteilen der Funktionsaufrufe
Es geht.
Mein größeres Problem ist eher, dass ich mich nicht wirklich auf den Server "verlassen kann". Soll heißen, die Messungen selber sind schlicht nicht reproduzierbar. Aber ok, vielleicht sind es die Tendenzen. Ich werde neben der absoluten zeit immer die Relation zur gesamten Scriptlaufzeit loggen.
Lösung 2: Einsatz eines echten Profilers
Den muss man nur erstmal auf den Server bekommen - wenn Du das nicht darfst, hat sich diese Variante erledigt.
Ich fürchte, das hat sich erledigt. Ich habe zwar relativ guten Webspace, aber der ist shared und somit dürfte sich das erledigt haben.
Jörg
Hallo Jörg,
Mein größeres Problem ist eher, dass ich mich nicht wirklich auf den Server "verlassen kann". Soll heißen, die Messungen selber sind schlicht nicht reproduzierbar
Das ist natürlich Käse. Du hast aber Anfang-zu-Ende Messungen im PHP drin, und die liefern die monströsen Schwankungen. Das schließt schonmal eine Menge von infrastrukturellen Problemen aus:
Dann schriebst Du:
Es sind aber zu viele Codezeilen, um jede Query oder ´jede php-Anweisung einzeln zu hinterfragen, bevor ich mich nicht in Richtung der Codepassage angenähert habe, die hier so stockt.
Und das ist nun das Entscheidende. Du musst die Knackpunkte finden, und das geht nur mit Kenntnis deines Codes.
Für das Sammeln der Profiling-Punkte solltest Du entweder ein globales Array anlegen, oder eine statische Klasse definieren (also eine Klasse ohne Instanz, die nur static-Methoden und -Properties enthält). Am Ende des Requests stoppst Du die Uhr und haust alle gesammelten Messpunkte in den Footer der Antwortseite. Das stellt sicher, dass Du nicht Messungen verschiedener Requests in einer Datei vermengst und die auseinander dröseln musst.
Wenn Du einen Autoloader für Klassen verwendest und den im Sourcecode hast: Messpunkte für das Autoloading schreiben. "Load class XY" - "Class XY loaded"
Hoffentlich holst Du Dir nur einmal eine DB-Verbindung. Vorher/Nachher.
Und dann teile deinen Code grob in 2-3 gleichgroße Abschnitte und schreibe Messpunkte, wenn Du dahin kommst. Die Hoffnung wäre, dass Du einen Abschnitt findest auf den sich der Zeitverlust konzentriert.
Bei einem Shared Hoster wäre meine Befürchtung allerdings, dass der Webserver oder der DB Server überlastet ist und generell zu langsam antwortet. Die overcommitten gerne ihr Blech und stellen nicht genug davon hin. Dann hilft nur meckern meckern meckern bei der Hotline - mit etwas Glück bekommst Du dann das Flag "sensibler user, nicht auf überlastete Server legen".
Oder dein Hosting-Angebot ist zu billig. Wat nix kost, dat taugt nix 😉
Rolf
Hallo Jörg,
Könnt Ihr mir Tips geben, wie ich hier vorgehen kann? (insb., da die Seite in ihren Messreihen so große Unterschiede macht und die Seite dennoch meist lange benötigt)
https://forum.selfhtml.org/self/2021/mar/04/css-performance-killer/1785253#m1785253
Gruss
Henry
Hallo Henry,
ich hatte Jörg so verstanden, dass er serverseitig die Laufzeit misst. Kann CSS da einen Einfluss haben?
Rolf
Hallo Rolf,
ich hatte Jörg so verstanden, dass er serverseitig die Laufzeit misst. Kann CSS da einen Einfluss haben?
nee. ging mir eh um diese seite: https://www.giftofspeed.com, wollte aber nicht nochmal schreiben 😉
Gruss
Henry
ich hatte Jörg so verstanden, dass er serverseitig die Laufzeit misst. Kann CSS da einen Einfluss haben?
Wenn man es mit ausreichend vielen ausreichend lang dauernden Datenbankabfragen zusammenbaut und/oder ausreichend viele ausreichend große base64-codierte Grafiken reinschiebt kann es das...
wobei manchmal über 6 Sekunden gemessen wird und manchmal nur 0,20 Sekunden.
Bevor ich messe würde ich nachdenken. Meine Glaskugel meint: Es kann „gut“ sein, dass bei den schnell laufenden SQL-Abfragen die Ergebnisse aus den Cache kommen (weil die der SQL-Server NOCH im Antwort-Cache hat), bei anderen ein Full-Table-Scan erforderlich wird. Und die sind „teuer“.
Wie viele Datensätze hast Du denn so in den Tabellen? Weniger als 1000? Dann wechsle den Anbieter.
Sind bei allen SQL-Anfragen die Spalten in WHERE, LIKE und ORDER-Klauseln indiziert?
Helfer im Terminal:
cd /var/www/htdocs;
grep -RnPi "WHERE |LIKE |ORDER ";
Wenn ja
cd /var/www/htdocs;
grep -Rni "LIKE.*%";
Wenn ja:
Stelle sicher, dass die Tabellen im InnoDB- oder MyIsam-format gespeichert sind und Lese hier und erzeuge einen FULLTEXT-Index. - oder hier: https://dev.mysql.com/doc/refman/5.6/en/fulltext-search.html
NUR wenn das nicht geht:
Baue eine Spalte foo_DESC, mach ein
UPDATE tabelle set `foo_DESC` REVERSE(`foo`);
und dann statt
SELECT foo, bar, baz FROM tabelle WHERE foo LIKE "%str";
eben
SELECT `foo`, `bar`, `baz` FROM tabelle WHERE `foo_DESC` LIKE "str%";
Du musst dann künftig jeden Neueintrag auch passend behandeln, alsofoo_DESC
mit dem REVERSE($string) befüllen...
Bei etwas wie
SELECT foo, bar, baz FROM tabelle WHERE foo LIKE "%str%";
musst Du ohne Fulltext-Index leider mit dem Problem leben.
SELECT `foo`, `bar`, `baz` FROM tabelle WHERE `foo_DESC` LIKE "str%";
so liefert es die erwarteten Ergebnisse:
SELECT `foo`, `bar`, `baz` FROM `tabelle` WHERE `foo_DESC` LIKE REVERSE("str%");