Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaScript Essentials: Speicherverwaltung (German)

JavaScript Essentials: Speicherverwaltung (German)

Speicherverwaltung in Javascript. Gibt es hierzu eigentlich viel zu sagen? Im Gegensatz zu unseren C++-Kollegen, müssen wir das Speichermanagement in unserer Anwendung nicht selbst entwickeln. Denn das JavaScript-Speichermanagement ist automatisiert und läuft im Hintergrund. Trotzdem müssen wir zumindest die grundlegenden Prinzipien verstehen, damit unser Code keine Speicherlecks aufweist.

In diesem Vortrag werden die Grundlagen der Speicherverwaltung behandelt. Danach sehen wir uns die Möglichkeiten der Chrome DevTools und bevor wir uns mit den möglichen Problemfällen befassen, gibt es einen Ausflug in die prinzipielle Funktionsweise eines Garbage Collectors.

Rainer Hahnekamp

June 26, 2019
Tweet

More Decks by Rainer Hahnekamp

Other Decks in Technology

Transcript

  1. Betriebssystem Prozess JavaScript Engine JavaScript Quelltext const product = {

    name: "Äpfel", category: "Früchte" }; Virtueller Speicher Speicherhierarchie
  2. Betriebssystem Prozess JavaScript Engine JavaScript Quelltext const product = {

    name: "Äpfel", category: "Früchte" }; Virtueller Speicher Stack Heap Speicherhierarchie
  3. Betriebssystem Prozess JavaScript Engine JavaScript Quelltext const product = {

    name: "Äpfel", category: "Früchte" }; Virtueller Speicher Heap Stack Speicherhierarchie Garbage Collector
  4. Heap Größen von Websites Website HEAP Google Suche 7 Amazon.de

    21 Twitter 42 Facebook 43 Slack 62 Google Slides 108 GMail 115 Google Maps (3D) 144
  5. Speicherallokation const doShopping = async () => { const basket

    = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ];total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; doShopping().then(console.log);
  6. Speicherallokation const doShopping = async () => { const basket

    = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") };n total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; doShopping().then(console.log);
  7. Speicherallokation const doShopping = async () => { const basket

    = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; doShopping().then(console.log);
  8. Speicherallokation const doShopping = async () => { const basket

    = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; };
  9. Speicherallokation const doShopping = async () => { const basket

    = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; Heap
  10. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; };
  11. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies
  12. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies total
  13. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); i=0 total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies total product (0)
  14. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); i=1 total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies total product (0) product (1)
  15. Speicherallokation Heap basket const doShopping = async () => {

    const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); i=2 total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies total product (0) product (1) Garbage Collection startet...
  16. Mark & Sweep Heap basket const doShopping = async ()

    => { const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 } ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); i=2 total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) { const currencies = { de: "€", gb: "£", cn: "¥" }; return currencies[country]; }; currencies total product (0) product (1) Garbage Collection starting...
  17. Infant Mortality Die meisten Objekten existieren nur eine kurze Zeit.

    Es wäre ineffizient, diese einzeln zu entfernen.
  18. Und es gibt noch mehr... const doShopping = async ()

    => { const basket = [ { product: "apple", amount: 3 }, { product: "water", amount: 1 }, { product: "milk", amount: 3 }, ··· ]; const total = { price: 0, currency: getCurrency("de") }; for (let i = 0; i < basket.length; i++) { const product = await fetchProduct(basket[i].product); total.price += product.price * basket[i].amount; } return total; }; const getCurrency = function(country) {··· }; mehrfache GCs noch mehr Produkte
  19. Reale Garbage Collectors • Variationen bzw. verbesserte Versionen: Das Prinzip

    ist jedoch dasselbe • Sehr viel Arbeit wird in schneller GC-Zyklen gesteckt. • Zusammenspiel mit der Rendering Engine des Browsers. • Anzahl der Objekte im Heap viel, viel höher.
  20. Globaler Scope 1/3 - kein var, let, const (function() {

    storage = new Array(1000000).fill("x"); })();
  21. Globaler Scope 2/3 - Typos (function() { let storage =

    ""; console.log("current length: " + storage.length); storge = new Array(1000000).fill("x"); })();
  22. Globaler Scope 3/3 - Falscher Context (function() { const person

    = { introduce: function() { console.log(this.introduction); }, setIntroduction: function(introduction) { this.introduction = introduction; } }; const getData = () => new Promise(resolve => resolve(new Array(1000000).fill("x"))); getData().then(person.setIntroduction); person.introduce(); })();
  23. DOM Nodes - losgelöste Elemente const ul = document.createElement("ul"); run5Times("detached",

    () => { for (let i = 0; i < 1000; i++) { ul.appendChild(document.createElement("li")); } });
  24. getPromotionFn getName printName data name async function getPromotionFn() { const

    data = await loadPromotion(); const getName = function() { return data[0]; }; const name = getName(); return function printName() { alert(`Kaufen Sie ${name}!!!`); }; } sollte im Speicher bleiben sollte entfernt werden (GC'ed)
  25. getPromotionFn Verschachtelte Funktionen teilen sich denselben Scope Scope getName printName

    data name data name async function getPromotionFn() { const data = await loadPromotion(); const getName = function() { return data[0]; }; const name = getName(); return function printName() { alert(`Kaufen Sie ${name}!!!`); }; }
  26. getPromotionFn Scope getName printName data name name async function getPromotionFn()

    { const data = await loadPromotion(); const getName = function() { return data[0]; }; const name = getName(); return function printName() { alert(`Kaufen Sie ${name}!!!`); }; }
  27. Zusammenfassung • Heap als Haupt-Speicherstruktur in JavaScript • Google DevTools

    ermöglichen ◦ Heap Dumps (statisch Analyse) ◦ Verwendung des Heaps über Zeitraum zu messen (dynamische Analyse) • Garbage Collectoren verwenden sogenannte Roots um zu bestimmen, ob ein Objekt de-allokiert werden kann • Garbage Collections laufen als "Batch" • Closure können schwer auffindbare Memory Leaks verursachen