Vergleich verschiedener Möglichkeiten zur Messung der Leistung von JavaScript-Funktionen

Vergleich verschiedener Möglichkeiten zur Messung der Leistung von JavaScript-Funktionen

Überblick

Durch Messen der zur Ausführung einer Funktion benötigten Zeit können Sie immer gut nachweisen, dass einige Implementierungen eine bessere Leistung als andere erbringen. Auf diese Weise können Sie außerdem sicherstellen, dass die Leistung nach einigen Änderungen nicht beeinträchtigt wurde, und Engpässe aufspüren.

Eine gute Leistung trägt zu einer guten Benutzererfahrung bei und eine gute Benutzererfahrung sorgt dafür, dass die Benutzer wiederkommen. Einer Studie zufolge ist es aufgrund von Leistungsproblemen weniger wahrscheinlich, dass 88 % der Online-Kunden nach einer schlechten Benutzererfahrung wiederkommen.

Deshalb ist es möglich, Engpässe in Ihrem Code zu identifizieren und Verbesserungen zu messen. Insbesondere bei der Entwicklung von JavaScript für Browser müssen Sie sich darüber im Klaren sein, dass jede Zeile JavaScript, die Sie schreiben, das Potenzial hat, den DOM zu blockieren, da es sich um eine Single-Thread-Sprache handelt.

In diesem Beitrag erkläre ich, wie Sie die Leistung Ihrer Funktionen messen können und was Sie mit den Ergebnissen tun können, die Sie daraus erhalten.

Leistung.jetzt

Die Performance-API bietet Zugriff auf DOMHighResTimeStamps über ihre Funktion performance.now(), die die seit dem Laden der Seite vergangene Zeit in Millisekunden mit einer Genauigkeit von bis zu Bruchteilen von 5 μs zurückgibt.

In der Praxis müssen Sie also zwei Zeitstempel nehmen, sie in einer Variablen speichern und dann den ersten vom zweiten Zeitstempel abziehen.

const t0 = Leistung.jetzt();
für (lass i = 0; i < Array.Länge; i++) {
  //etwas Code
}
const t1 = Leistung.jetzt();
console.log(t1 - t0, 'Millisekunden');

Chrome-Ausgabe

0,6350000001020817 „Millisekunden“

Firefox-Ausgabe

1 Millisekunde

Hier können wir sehen, dass die Ergebnisse in Firefox völlig anders sind als in Chrome. Das liegt daran, dass in Firefox Version 60 die Präzision der Performance-API auf 2 ms reduziert wurde.

Die Performance-API bietet weitaus mehr Funktionen als nur die Rückgabe eines Zeitstempels; sie kann auch die Navigations-, Benutzer- oder Ressourcenzeit messen. Eine ausführlichere Erklärung finden Sie in diesem Artikel.

Für unseren Anwendungsfall möchten wir jedoch nur die Leistung einer einzelnen Funktion messen, sodass ein Zeitstempel ausreichend ist.

Ist das nicht dasselbe wie Date.now?

Jetzt denkst du vielleicht: Das könnte ich auch mit Date.now machen.

Ja, das können Sie, aber es gibt Nachteile.

Date.now gibt die Zeit in Millisekunden seit der Unix-Epoche („1970-01-01-01T00:00:00:00Z“) zurück und ist von der Systemuhr abhängig. Dies bedeutet nicht nur, dass die Genauigkeit geringer ist, sondern auch, dass die Werte nicht unbedingt zunehmen werden. Der WebKit-Ingenieur (Tony Gentilcore) hat es folgendermaßen erklärt:

Weniger beachtet ist jedoch, dass ein auf der Systemzeit basierendes Datum für eine echte Benutzerüberwachung ebenfalls nicht ideal ist. Auf den meisten Systemen läuft ein Daemon, der die Zeit regelmäßig synchronisiert. Typischerweise wird die Uhr alle 15–20 Minuten um einige Millisekunden verstellt. Bei dieser Rate sind etwa 1 % der 10-Sekunden-Intervalle ungenau.

Konsole.Zeit

Die API ist wirklich einfach zu verwenden: Setzen Sie einfach console.time vor den Code, den Sie messen möchten, und console.timeEnd nach den Code, den Sie messen möchten, rufen Sie die Funktion mit demselben String-Parameter auf, und Sie können bis zu 10.000 Timer gleichzeitig auf einer Seite verwenden.

Die Genauigkeit ist die gleiche wie bei der Performance-API, ist aber wiederum browserabhängig.

Konsole.Zeit('Test');
für (lass i = 0; i < Array.Länge; i++) {
  //etwas Code
}
Konsole.timeEnd('Test');

Dadurch wird automatisch eine für Menschen lesbare Ausgabe generiert, wie unten gezeigt:

Chrome-Ausgabe

Test: 0,766845703125 ms

Firefox-Ausgabe

Test: 2 ms – Timer abgelaufen

Die Ausgabe hier ist wieder der Performance-API sehr ähnlich.

Der Vorteil von console.time besteht in der einfachen Verwendung, da die Differenz zwischen zwei Zeitstempeln nicht manuell berechnet werden muss.

Verkürzung der Zeitgenauigkeit

Wenn Sie Ihre Funktionen mithilfe der oben genannten APIs in unterschiedlichen Browsern messen, stellen Sie möglicherweise fest, dass die Ergebnisse unterschiedlich ausfallen.

Dies liegt daran, dass der Browser versucht, Benutzer vor Timing-Angriffen und Fingerprinting-Angriffen zu schützen. Wenn der Zeitstempel zu genau ist, könnte ein Hacker ihn verwenden, um den Benutzer zu identifizieren.

Beispielsweise versuchen Browser wie Firefox dies zu verhindern, indem sie die Präzision auf 2ms reduzieren (Version 60).

Dinge zu beachten

Jetzt verfügen Sie über die Tools, die Sie zum Messen der Geschwindigkeit Ihrer JavaScript-Funktionen benötigen. Es gibt jedoch einige Fallstricke, die man besser vermeidet.

Teile und herrsche

Sie bemerken, dass beim Filtern einiger Ergebnisse etwas langsam ist, wissen aber nicht, wo der Engpass liegt.

Anstatt zu raten, welcher Teil Ihres Codes langsam ist, verwenden Sie diese Funktionen, um ihn zu messen.

Um es aufzuspüren, platzieren Sie zunächst Ihre console.time-Anweisungen um den langsamen Codeblock herum. Messen Sie dann die Leistung unterschiedlicher Teile und wenn ein Teil langsamer ist als die anderen, gehen Sie diesen Weg weiter und jedes Mal tiefer, bis Sie den Engpass finden.

Je weniger Code zwischen diesen Anweisungen steht, desto unwahrscheinlicher ist es, dass Sie etwas verfolgen, das Sie nicht interessiert.

Notieren Sie den Eingabewert

In realen Anwendungen können die Eingabewerte einer gegebenen Funktion stark variieren. Die Geschwindigkeit einer Funktion einfach für beliebige Zufallswerte zu messen, liefert für uns keine wertvollen Daten, die wir tatsächlich nutzen können.

Stellen Sie sicher, dass Sie den Code mit denselben Eingabewerten ausführen.

Mehrmaliges Ausführen einer Funktion

Angenommen, Sie haben eine Funktion, die über ein Array iteriert, für jeden Array-Wert eine Berechnung durchführt und ein Array mit den Ergebnissen zurückgibt. Sie möchten wissen, ob forEach oder eine einfache for-Schleife effizienter ist.

Hier ist die Funktion:

Funktion testForEach(x) {
  Konsole.Zeit('test-forEach');
  Konstantenres = [];
  x.forEach((Wert, Index) => {
    res.push(Wert / 1,2 * 0,1);
  });

  Konsole.timeEnd('test-forEach')
  Rückgabewert;
}

Funktion testFor(x) {
  Konsole.Zeit('Test für');
  Konstantenres = [];
  für (sei i = 0; i < x.Länge; i++) {
    res.push(x[i] / 1,2 * 0,1);
  }

  Konsole.timeEnd('test-für')
  Rückgabewert;
}

Sie können sie folgendermaßen testen:

const x = neues Array(100000).fill(Math.random());
testForEach(x);
testFür(x);

Wenn Sie die obige Funktion in Firefox ausführen, erhalten Sie eine Ausgabe ähnlich der folgenden:

test-forEach: 27 ms – Timer abgelaufen

test-for: 3ms - Timer abgelaufen

Es sieht so aus, als ob forEach langsam ist, oder?

Sehen wir uns an, ob wir die gleiche Funktion zweimal mit der gleichen Eingabe ausführen:

testForEach(x);

testForEach(x);

testFür(x);

testFür(x);

test-forEach: 13 ms – Timer abgelaufen

test-forEach: 2 ms – Timer abgelaufen

test-for: 1ms - Timer abgelaufen

test-for: 3ms - Timer abgelaufen

Wenn wir den forEach-Test ein zweites Mal aufrufen, ist die Leistung genauso gut wie bei der for-Schleife. Angesichts des langsamen Anfangswerts lohnt es sich wahrscheinlich sowieso nicht, forEach zu verwenden.

...in mehreren Browsern

Wenn wir den obigen Code in Chrome ausführen, sehen die Ergebnisse plötzlich anders aus:

test-fürJeden: 6,156005859375 ms

test-fürJeden: 8,01416015625 ms

Test für: 4,371337890625 ms

Test für: 4,31298828125 ms

Dies liegt daran, dass Chrome und Firefox unterschiedliche JavaScript-Engines mit verschiedenen Arten von Leistungsoptimierungen haben. Es ist gut, sich dieser Unterschiede bewusst zu sein.

In diesem Fall optimiert Firefox die Verwendung von forEach besser für dieselbe Eingabe.

Die Leistung von for ist auf beiden Engines besser, daher ist es am besten, bei der for-Schleife zu bleiben.

Dies ist ein gutes Beispiel dafür, warum Sie in mehreren Engines messen sollten. Wenn Sie nur Chrome zur Messung verwenden, kommen Sie möglicherweise zu dem Schluss, dass forEach im Vergleich zu for gar nicht so schlecht ist.

Drosselung Ihrer CPU

Diese Zahlen sehen nicht hoch aus. Bedenken Sie, dass Ihr Entwicklungscomputer normalerweise viel schneller ist als das durchschnittliche Mobiltelefon, auf dem Ihre Website angezeigt wird.

Um ein Gefühl dafür zu bekommen, wie das aussieht: Browser verfügen über eine Funktion, mit der Sie die CPU-Leistung drosseln können.

Aus den 10 bzw. 50ms wurden dadurch schnell 500ms.

Messung der relativen Leistung

Diese Rohergebnisse hängen tatsächlich nicht nur von Ihrer Hardware, sondern auch von Ihrer CPU und der aktuellen Auslastung Ihres JavaScript-Threads ab. Versuchen Sie, sich bei Ihren Messungen auf die relativen Verbesserungen zu konzentrieren, da die Zahlen beim nächsten Neustart Ihres PCs möglicherweise ganz anders aussehen.

Zusammenfassen

In diesem Artikel haben wir einige JavaScript-APIs gesehen, mit denen wir die Leistung messen können, und wie man sie in der „realen Welt“ einsetzt. Für einfache Messungen finde ich es einfacher, console.time zu verwenden.

Ich habe den Eindruck, dass sich viele Frontend-Entwickler im Alltag nicht genügend Gedanken über die Leistung machen, obwohl diese direkte Auswirkungen auf den Umsatz hat.

Oben finden Sie den detaillierten Inhalt des Vergleichs verschiedener Methoden zur Messung der Leistung von JavaScript-Funktionen. Weitere Informationen zur Leistung von JavaScript-Funktionen finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Implementierungsmethode und Vorteile der JS-Leistungsoptimierung
  • Methode zum Vergleichen der Leistung von JS-Funktionen
  • Beispiel für einen Leistungstest in JavaScript für eine For-Loop
  • Detaillierter Leistungsvergleich mehrerer häufig verwendeter JSON-Bibliotheken in Java
  • Drei Methoden zur Zeichenfolgenverkettung in Javascript und Leistungsvergleich
  • Was Sie bei der Implementierung von leistungsstarkem JavaScript beachten sollten
  • Natives JS zum verzögerten Laden von Bildern und zur Optimierung der Seitenleistung
  • Pfad zur Leistungsverbesserung in JavaScript (empfohlen)
  • Entwicklung und Leistungsanalyse von JavaScript-Arrays

<<:  Grundlagen der MySQL-Speicher-Engine

>>:  Erfahren Sie, wie nginx hohe Leistung und Skalierbarkeit erreicht.

Artikel empfehlen

Vue realisiert die Palastgitterrotationslotterie

Vue implementiert die Palastgitterrotationslotter...

Ideen zum Erstellen von Welleneffekten mit CSS

Zuvor habe ich mehrere Möglichkeiten vorgestellt,...

Das WeChat-Applet realisiert einen mehrzeiligen Text-Scroll-Effekt

In diesem Artikelbeispiel wird der spezifische Co...

Langsame MySQL-Abfrage: Langsame Abfrage aktivieren

1. Was nützt eine langsame Abfrage? Es kann alle ...

So konfigurieren Sie geplante MySQL-Aufgaben (EVENT-Ereignisse) im Detail

Inhaltsverzeichnis 1. Was ist eine Veranstaltung?...

Detaillierte Erläuterung der Konzepte und Verwendung von Docker Swarm

Docker Swarm ist ein von Docker entwickelter Cont...

MySQL sql_mode-Analyse und Einstellungserklärung

Beim Einfügen eines Datensatzes in die MySQL-Date...

Zen Coding Einfaches und schnelles HTML-Schreiben

Zen-Codierung Es ist ein Texteditor-Plugin. In ei...