JavaScript Performance

884 Aufrufe

Veröffentlicht am

Best Practices und Werkzeuge, wenn es um Performance in JavaScript geht.

Veröffentlicht in: Software
0 Kommentare
1 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
884
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
76
Aktionen
Geteilt
0
Downloads
5
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

JavaScript Performance

  1. 1. JavaScript Performance
  2. 2. WHO AM I? • Sebastian Springer • aus München • arbeite bei Mayflower • https://github.com/sspringer82 • @basti_springer • Consultant,Trainer,Autor
  3. 3. Wie öffnet ihr eure Dev Tools im Browser? • Was sind Dev Tools? • Tastenkombination • Mausklick (maximal 2)
  4. 4. Was erwartet euch? Best Practices: Wie kann ich Probleme von vornherein vermeiden? Performance Optimierung: Was mache ich, wenn meine Applikation langsam ist?
  5. 5. Performance Es gibt nicht die eine JavaScript Performance. Wie sich eine Applikation benimmt, hängt von zahlreichen Komponenten ab. Die wichtigsten sind Netzwerk, CPU, Memory und Rendering.
  6. 6. Performance verbessern Branko Spoljar / pixelio.de Karl-Heinz Laube / pixelio.de
  7. 7. Vorgehensweise Ein kleiner Ausflug: Andreas Hermsdorf / pixelio.de
  8. 8. Vorgehensweise Analyse Bewertung Durchführung Kontrolle Thorben Wengert / pixelio.de
  9. 9. Analyse Tim Reckmann / pixelio.de
  10. 10. Developer Tools
  11. 11. Analyse Meist weiß man, wo die Applikation langsam ist. Ansonsten werden CPU, Memory, Rendering und Netzwerk überprüft. Konkrete Messwerte für den späteren Vergleich festhalten. Profile-Daten können gespeichert, geladen und verglichen werden.
  12. 12. Bewertung bschpic / pixelio.de
  13. 13. Bewertung Meist findet man mehrere Problemstellungen, hat jedoch nicht genügend Ressourcen. Also Kosten-Nutzen- Abwägung durchführen. Cheap Wins zuerst durchführen, gravierende Umbauten mit wenig Benefits eher nicht durchführen. Erwartete Verbesserung oder Zielmetrik festhalten.
  14. 14. Bewertung Maßnahme Aufwand Nutzen GZIP Compression — + Concat & Uglify + ++ DOM verkleinern ++ + DOM Operationen gruppieren ++ ++ … … …
  15. 15. Durchführung I-vista / pixelio.de
  16. 16. Durchführung Anpassung des Quellcodes. Es sollte auf jeden Fall ein Versionskontrollsystem (git, svn) eingesetzt werden. So können die Stände verglichen und falls nötig zurückgesetzt werden. Tests nicht vergessen!
  17. 17. Kontrolle Tim Reckmann / pixelio.de
  18. 18. Kontrolle Die Messwerte der Analyse werden mit den aktuellen Werten der Applikation verglichen. Im Anschluss steht die Entscheidung, ob weitere Verbesserungen erforderlich sind oder ob weitere Maßnahmen keinen erheblichen Mehrwert bieten.
  19. 19. Performance Netzwerk CPU Memory Rendering
  20. 20. Netzwerk Klicker / pixelio.de
  21. 21. Netzwerk Anfragen vom Client an den Server über HTTP. Browser haben nur eine gewisse Anzahl an parallelen Requests pro Subdomain.
  22. 22. Netzwerk https://developer.chrome.com/devtools/docs/network Navigation Timing API: https://developer.mozilla.org/en-US/ docs/Navigation_timing
  23. 23. Netzwerk
  24. 24. Netzwerk • Stalled/Blocking: Zeit, bevor die Anfrage gesendet wird. • Proxy Negotiation: Verbinden mit Proxy. • DNS Lookup: Hostnamen auflösen. • Initial Connection: TCP Handshake, SSL Negotiation • SSL: SSL Handshake • Request Sent: Versenden der Anfrage. • Waiting (TTFB): Initiale Antwort des Servers. • Content Download: Herunterladen der Antwort.
  25. 25. Netzwerk • Anzahl der Requests reduzieren • Größe der Responses reduzieren • gzip aktivieren • DNS Lookups reduzieren (wenige unterschiedliche Hosts) • Caching
  26. 26. CPU Tim Reckmann / pixelio.de
  27. 27. CPU Prozessor-Ressourcen, die benötigt werden, um den JavaScript-Quellcode auszuführen. Die meiste Performance geht aber durch DOM-Operationen verloren.
  28. 28. CPU JavaScript Engines weisen zahlreiche Optimierungen auf. Häufig liegen die Probleme nicht an der Ausführung des JavaScript-Quellcodes.
  29. 29. Hidden Classes Optimierung des Browsers, um schneller auf Eigenschaften von Objekten zuzugreifen.
  30. 30. Maschinencode Generierung point.x # ebx = the point object cmp [ebx,<hidden class offset>],<cached hidden class> jne <inline cache miss> mov eax,[ebx, <cached x offset>] Gibt es für die Eigenschaft eine Hidden Class, wird diese verwendet. Ansonsten wird der Cache Miss behandelt. Dann wird der Wert für die Eigenschaft ausgeliefert.
  31. 31. Garbage Collection Aufräumen des Speichers. Zwei Speicherbereiche. Mit unterschiedlichen Algorithmen. GC benötigt Zeit, hält die Applikation komplett an. Das kann zu Ruckeln in Applikationen führen.
  32. 32. Timeline Die Timeline der Chrome Developer Tools gibt einen ersten Überblick über CPU und Memory Daten und ist ein guter Ausgangspunkt für die Analyse von Performance-Problemen.
  33. 33. Timeline
  34. 34. CPU Das CPU-Profile gibt genaueren Aufschluss darüber, welche Routinen wie viele Ressourcen benötigt haben. Drei verschiedene Darstellungsarten: - Chart: Flame Chart - Heavy (Bottom up): Tablle mit den teuersten Routinen oben - Tree (Top Down): Baumdarstellung
  35. 35. CPU
  36. 36. CPU - Chart Eine Funktion hat immer die gleiche Farbe. Erleichtert die Mustererkennung. Simulieren Callstacks jeweils mit Verweis auf die entsprechende Codestelle. Name: Funktionsname Self time: Zeit der Funktion selbst Total time: Zeit der Funktion und aller Unterfunktionen Aggregated self time: Summe der self time aller Aufrufe Aggregated total time: Summe der total time aller Aufrufe
  37. 37. CPU
  38. 38. CPU
  39. 39. Call Graphs? code2flow: experimentelles Tool zur Generierung von Call Graphs https://github.com/scottrogowski/code2flow
  40. 40. https://github.com/scottrogowski/code2flow/blob/master/jqueryexample.png Call Graph für jQuery
  41. 41. Memory Jan von Bröckel / pixelio.de
  42. 42. Memory Arbeitsspeicher, der durch die Applikation verbraucht wird. JavaScript-Objekte, Repräsentationen von DOM-Elementen, …
  43. 43. Heap Snapshot Radka Schöne / pixelio.de
  44. 44. Heap Snapshot • Summary: Zusammenfassung • Comparison: Vergleich zweier Snapshots • Containment: Übersicht über die Objektstruktur • Statistics: Verteilung des Speichers auf Objekttypen Verschiedene Views: Abbild des aktuellen Speichers.
  45. 45. Heap Snapshot Shallow Size: Speicher, den ein Objekt selbst benötigt. Retained Size: Speicher, den ein Objekt und die nur von ihm referenzierten Objekte benötigen. Distance: Kürzester Weg durch die Memory Hierarchie.
  46. 46. Record Heap Allocations Tim Reckmann / pixelio.de
  47. 47. Record Heap Allocations Wie der Snapshot, nur über Zeit gesehen. Zum Auffinden von Memory Leaks.
  48. 48. Rendering Burkard Vogt / pixelio.de
  49. 49. Rendering Reflow: Neuberechnung der Positionen und Geometrie von DOM-Elementen. Blockierende Operation. Wann passieren Reflows: DOM-Elemente hinzufügen/ entfernen, Klassen anpassen, …
  50. 50. bschpic / pixelio.de Best Practices
  51. 51. Best Practices Was kann man bereits bei der Entwicklung beachten, um Performance-Probleme zu vermeiden?
  52. 52. Webworkers Komplexe Berechnungen verzögern die Ausführung und Blockieren die Applikation. Mit HTML5 kommen Webworker: Kindprozesse im Browser. Kommunikation über Nachrichten. Workerprozess hat Zugriff auf: navigator, location, xhr, timing, Kein Zugriff auf: DOM, window, document, parent
  53. 53. Webworkers var worker = new Worker('worker.js');
 
 worker.postMessage('Hello Worker');
 
 worker.addEventListener('message', function (data) {
 console.log(data);
 }); index.js worker.js self.addEventListener('message', function (data) {
 self.postMessage('Hello Main');
 });
  54. 54. Variablen und Datenstrukturen Lokale Variablen nutzen, ist schneller als Property-Zugriff und Array-Zugriff. Objekte und Properties cachen. Je tiefer ein Array strukturiert ist, desto langsamer wird der Zugriff.
  55. 55. Prototypen und Methoden function Calculator() {
 this.add = function () {}
 } function Calculator() {}
 
 Calculator.prototype.add = function () {}; vs Für jede Instanz wird ein neues Funktionsobjekt erzeugt und eine neue Closure generiert, was alles Speicherplatz benötigt.
  56. 56. Prototypen und Werte function Calculator() {
 this.a = 1;
 this.b = {};
 } function Calculator() {
 this.b = {};
 }
 
 Calculator.prototype.a = 1; vs Initialisierungslogik muss nicht jedes Mal durchlaufen werden.
  57. 57. Closures Eine Closure ist eine Funktion und ihr erstellender Kontext. Benötigt also für die Funktion und den erstellenden Kontext Speicher. Quelle für Memoryleaks. DOM-Elemente zeigen auf Closures und umgekehrt. GC kann nicht aufräumen. Sobald eine Callback-Funktion registriert wird, kann sie nicht durch den GC freigegeben werden. Callbacks sollten deregistriert werden.
  58. 58. function async() {
 var msg = 'Hello World';
 setTimeout(function() {
 console.log(msg);
 }, 1000);
 } Inner Funktion mit Closure function async() {
 setTimeout(function() {
 var msg = 'Hello World';
 console.log(msg);
 }, 1000);
 } Inner Funktion ohne Closure function sayHello() {
 var msg = 'Hello World';
 console.log(msg);
 
 }
 function async() {
 setTimeout(sayHello, 1000);
 } Statische Funktion Schnell Langsam
  59. 59. Closures Zugriff auf Variablen wird langsamer durch zusätzliche Scopes. Je weiter nach außen, desto langsamer wird es. function createFunctionWithClosure() {
 var b = 'b';
 return function () {
 var c = 'c';
 a;
 b;
 c;
 };
 } createFunctionWithClosure(); c > b > a
  60. 60. Kein with Die Scope Chain wird modifiziert. Es wird teurer, auf Variablen zuzugreifen. var a, x, y;
 var r = 10;
 
 with (Math) {
 a = PI * r * r;
 x = r * cos(PI);
 y = r * sin(PI / 2);
 }
  61. 61. Browser Memory Leaks Expando Properties: Beliebige Eigenschaften auf DOM- Objekten ,die z.B. zirkuläre Referenzen halten können. Obj A > Obj B > Obj A Im besten Fall komplett vermeiden.
  62. 62. Arbeit in Schleifen reduzieren Jedes Statement in einer Schleife wird pro Schleifendurchlauf ausgeführt. Funktionsdefinitionen oder Ähnliches vermeiden. Möglichst statischen Code außerhalb und wirklich nur das Nötigste in der Schleife halten. for (var i = 0; i < arr.length; i++) {} var length = arr.length;
 for (var i = 0; i < length; i++) {}
  63. 63. Rendering DOM einfach und flach halten. Möglichst wenige CSS Regeln. Für komplexes Rendering - position: absolute oder position: fixed Einfache CSS Selektoren.
  64. 64. Wenige DOM-Zugriffe DOM-Zugriffe nur wenn erforderlich. Zusammenfassen von DOM-Zugriffen. Elemente wiederverwenden.
  65. 65. Unnötige Variablen vermeiden var name = firstname + ' ' + lastname;
 console.log(name); console.log(firstname + ' ' + lastname); vs. Jede Variable benötigt Speicherplatz. Der GC bekommt Arbeit.
  66. 66. JavaScript spät laden JavaScript im Fuß der Seite laden. JavaScript möglichst asynchron laden. Alternative ist <script defer=“true” src=“”></script> JS wird nach dem Parsen geladen. <script async src=“”></script> JS wird parallel zum Parsen geladen.
  67. 67. JavaScript on demand laden RequireJS erlaubt nachträgliches Laden von Dateien zur Laufzeit. Auch mit Browserify ist Lazy Loading möglich.
  68. 68. Achtung Keine Premature Optimization - die richtigen Optimierungen erst, wenn man sie braucht. Keine Mikrooptimierung Der Quellcode soll lesbar und wartbar bleiben.
  69. 69. Fragen? Rainer Sturm / pixelio.de
  70. 70. KONTAKT Sebastian Springer sebastian.springer@mayflower.de Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland @basti_springer https://github.com/sspringer82

×