แก้ปัญหาเกี่ยวกับหน่วยความจำ

ดูวิธีใช้ Chrome และเครื่องมือสําหรับนักพัฒนาเว็บเพื่อค้นหาปัญหาเกี่ยวกับหน่วยความจําที่ส่งผลกระทบต่อประสิทธิภาพของหน้าเว็บ รวมถึง หน่วยความจำรั่วไหล หน่วยความจำไม่พอ และการขยะจำนวนมากบ่อยๆ

สรุป

  • ดูว่าหน้าเว็บของคุณใช้หน่วยความจำมากเพียงใดด้วยตัวจัดการงานของ Chrome
  • แสดงภาพการใช้งานหน่วยความจำเมื่อเวลาผ่านไปด้วยการบันทึกไทม์ไลน์
  • ระบุต้นไม้ DOM ที่ถอดออก (สาเหตุที่พบบ่อยของการรั่วไหลของหน่วยความจำ) ด้วยสแนปชอตฮีป
  • ดูว่าเมื่อใดที่มีการจัดสรรความทรงจำใหม่ในฮีป JS ด้วยการบันทึกไทม์ไลน์การจัดสรร

ภาพรวม

ตามเจตนาของโมเดลประสิทธิภาพ RAIL สิ่งที่คุณมุ่งเน้นคือความพยายามในการเพิ่มประสิทธิภาพ ผู้ใช้ของคุณ

ปัญหาเกี่ยวกับความจำมีความสำคัญเนื่องจากผู้ใช้มักมองเห็นปัญหาเหล่านี้ ผู้ใช้รับรู้หน่วยความจำได้ ปัญหาในลักษณะต่อไปนี้

  • ประสิทธิภาพของหน้าเว็บจะแย่ลงเรื่อยๆ เมื่อเวลาผ่านไป นี่อาจเป็นอาการของ หน่วยความจำรั่วไหล การรั่วไหลของหน่วยความจำเกิดขึ้นเมื่อข้อบกพร่องในหน้าทำให้หน้ามีการใช้งานมากขึ้นเรื่อยๆ หน่วยความจำมากขึ้นเมื่อเวลาผ่านไป
  • ประสิทธิภาพของหน้าเว็บไม่ดีอย่างต่อเนื่อง อาจเป็นอาการของหน่วยความจำมาก หน่วยความจำ bloat เกิดขึ้นเมื่อหน้าเว็บใช้หน่วยความจำมากกว่าที่จำเป็นเพื่อให้มีความเร็วหน้าเว็บสูงสุด
  • ประสิทธิภาพของหน้าเว็บล่าช้าหรือหยุดชั่วคราวบ่อยครั้ง นี่อาจเป็นอาการของ การทิ้งขยะบ่อยๆ การเก็บรวบรวมขยะเกิดขึ้นเมื่อเบราว์เซอร์เรียกคืนหน่วยความจำ เบราว์เซอร์ การตัดสินใจเกี่ยวกับเวลาที่จะดำเนินการดังกล่าว ในระหว่างการรวบรวม การทำงานของสคริปต์ทั้งหมดจะหยุดชั่วคราว ดังนั้นถ้าเบราว์เซอร์ คือการเก็บรวบรวมขยะจำนวนมาก การดำเนินการสคริปต์จะหยุดชั่วคราวอย่างมาก

หน่วยความจำมาก: "มากเกินไป" แค่ไหน

การรั่วไหลของหน่วยความจำนั้นทำได้ง่าย หากเว็บไซต์มีการใช้หน่วยความจำมากขึ้นเรื่อยๆ แสดงว่า รั่วไหล แต่หน่วยความจำมากจนเกินไปจะปักหมุดได้ยากกว่า ข้อใดจัดว่าเป็น "การใช้หน่วยความจำมากเกินไป"

ส่วนนี้ไม่มีตัวเลขตายตัว เนื่องจากอุปกรณ์และเบราว์เซอร์ต่างๆ มีความสามารถแตกต่างกัน หน้าเว็บเดียวกันที่ทำงานได้อย่างราบรื่นในสมาร์ทโฟนระดับไฮเอนด์อาจขัดข้องในสมาร์ทโฟนระดับโลว์เอนด์

กุญแจสำคัญในที่นี้คือการใช้โมเดล RAIL และมุ่งเน้นที่ผู้ใช้ ดูว่าอุปกรณ์ใดเป็นที่นิยม กับผู้ใช้ของคุณ จากนั้นจึงทดสอบหน้าเว็บบนอุปกรณ์เหล่านั้น หากการใช้งานเป็นไปอย่างสม่ำเสมอ แสดงว่าหน้าเว็บอาจมีหน่วยความจำเกินขีดจำกัดของอุปกรณ์เหล่านั้น

ตรวจสอบการใช้หน่วยความจำแบบเรียลไทม์ด้วยตัวจัดการงานของ Chrome

ใช้ตัวจัดการงาน Chrome เป็นจุดเริ่มต้นในการตรวจสอบปัญหาเกี่ยวกับหน่วยความจำ ตัวจัดการงาน คือเครื่องมือตรวจสอบแบบเรียลไทม์ที่บอกปริมาณหน่วยความจำที่หน้าเว็บใช้อยู่ในปัจจุบัน

  1. กด Shift+Esc หรือไปที่เมนูหลักของ Chrome แล้วเลือกเครื่องมือเพิ่มเติม > ตัวจัดการงานเพื่อ เปิดตัวจัดการงาน

    เปิดตัวจัดการงาน

  2. คลิกขวาที่ส่วนหัวของตารางของตัวจัดการงาน และเปิดใช้หน่วยความจำ JavaScript

    กำลังเปิดใช้งานหน่วยความจำ JS

คอลัมน์ทั้งสองนี้จะบอกคุณเกี่ยวกับสิ่งที่หน้าเว็บใช้หน่วยความจำแตกต่างกัน

  • คอลัมน์หน่วยความจำจะแสดงหน่วยความจำดั้งเดิม โหนด DOM จะจัดเก็บไว้ในหน่วยความจำของระบบ หากสิ่งนี้ มูลค่าเพิ่มสูงขึ้น ระบบกำลังสร้างโหนด DOM
  • คอลัมน์หน่วยความจำ JavaScript จะแสดงฮีป JS คอลัมน์นี้มี 2 ค่า ค่าที่คุณสนใจคือหมายเลขปัจจุบัน (ตัวเลขในวงเล็บ) หมายเลขโทรศัพท์แบบสด แสดงว่าออบเจ็กต์ที่เข้าถึงได้บนหน้าเว็บของคุณใช้หน่วยความจำมากเพียงใด หากหมายเลขนี้คือ เพิ่มขึ้น ไม่ว่าจะมีการสร้างออบเจ็กต์ใหม่ หรือออบเจ็กต์เดิมก็กำลังเติบโตขึ้นเรื่อยๆ

แสดงภาพหน่วยความจำรั่วไหลด้วยการบันทึกประสิทธิภาพ

นอกจากนี้ คุณยังใช้แผงประสิทธิภาพเป็นจุดเริ่มต้นอีกจุดหนึ่งในการตรวจสอบได้ด้วย ประสิทธิภาพ จะช่วยให้คุณเห็นภาพการใช้หน่วยความจำของหน้าเว็บในช่วงเวลาหนึ่ง

  1. เปิดแผงประสิทธิภาพในเครื่องมือสำหรับนักพัฒนาเว็บ
  2. เปิดใช้ช่องทำเครื่องหมายหน่วยความจำ
  3. บันทึกวิดีโอ

ลองดูโค้ดด้านล่างเพื่อแสดงการบันทึกหน่วยความจำของประสิทธิภาพ

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

ทุกครั้งที่มีการกดปุ่มที่อ้างอิงในโค้ด จะมีการเพิ่มโหนด div เพิ่ม 10, 000 โหนด ที่ส่วนเนื้อหาของเอกสาร และสตริงอักขระ 1 ล้านตัว x จะถูกพุชเข้าไปในอาร์เรย์ x การเรียกใช้โค้ดนี้จะบันทึกไทม์ไลน์เช่นภาพหน้าจอต่อไปนี้

ตัวอย่างการเติบโตอย่างง่าย

อย่างแรกคือคำอธิบายอินเทอร์เฟซผู้ใช้ กราฟ HEAP ในแผงภาพรวม (ด้านล่าง NET) แสดงถึงฮีป JS ด้านล่างแผงภาพรวมคือแผงตัวนับ ที่นี่คุณสามารถ ดูการใช้งานหน่วยความจำที่แบ่งตามฮีป JS (เหมือนกับกราฟ HEAP ในแผงภาพรวม) เอกสาร, โหนด DOM, Listener และหน่วยความจำ GPU การปิดใช้ช่องทำเครื่องหมายจะซ่อนช่องจากกราฟ

ตอนนี้เป็นการวิเคราะห์โค้ดเทียบกับภาพหน้าจอ หากคุณดูที่ตัวนับโหนด (พารามิเตอร์ กราฟสีเขียว) คุณจะเห็นว่ากราฟนั้นตรงกับโค้ดอย่างชัดเจน จำนวนโหนดเพิ่มขึ้นใน ขั้นตอนที่แยกออกจากกัน คุณสามารถสันนิษฐานว่าจำนวนโหนดที่เพิ่มขึ้นแต่ละครั้งเป็นการเรียก grow() JS กราฟฮีป (กราฟสีน้ำเงิน) นั้นไม่ตรงไปตรงมา ในการปฏิบัติตามแนวทางปฏิบัติแนะนำ ช่วงที่ลดลงแรก คือการบังคับให้เก็บขยะ (ทำได้โดยกดปุ่ม collect garbage) อาส การบันทึกจะดำเนินไปอยู่ คุณจะเห็นได้ว่าขนาดฮีป JS เพิ่มสูงขึ้น ซึ่งเป็นเรื่องปกติและเป็นไปตามที่คาดไว้ โค้ด JavaScript สร้างโหนด DOM เมื่อมีการคลิกปุ่มแต่ละครั้งและจะทำงานหนักมาก จะสร้างสตริงที่มีอักขระ 1 ล้านตัว สิ่งสำคัญที่นี่คือข้อเท็จจริงที่ว่าฮีป JS สิ้นสุด สูงกว่าเวลาเริ่ม ("จุดเริ่มต้น" ในที่นี้คือจุดหลังจากการบังคับเก็บขยะ) ใน ถ้าคุณเห็นรูปแบบของการเพิ่มขนาดฮีป JS หรือขนาดโหนดแบบนี้ อาจหมายถึงหน่วยความจำรั่ว

ค้นพบการรั่วไหลของหน่วยความจำแผนผัง DOM ที่ปลดออกด้วยสแนปชอตฮีป

ระบบจะรวบรวมโหนด DOM ได้เฉพาะที่ไม่มีการอ้างอิงโหนดดังกล่าวจากโค้ดของหน้าเว็บ แผนผัง DOM หรือโค้ด JavaScript มีโหนดว่า "ปลดออก" เมื่อนำออกจากแผนผัง DOM แต่ JavaScript บางตัวก็ยังคงอ้างอิงถึง URL นั้น โหนด DOM ที่ถูกปลดออกคือสาเหตุที่พบบ่อยของการรั่วไหลของหน่วยความจำ ช่วงเวลานี้ จะสอนวิธีใช้เครื่องมือสำหรับนักพัฒนาเว็บ ตัวสร้างโปรไฟล์ฮีปเพื่อระบุโหนดที่ปลดออก

ต่อไปนี้เป็นตัวอย่างง่ายๆ ของโหนด DOM ที่ปลดออกแล้ว

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

การคลิกปุ่มที่อ้างอิงในโค้ดจะสร้างโหนด ul ที่มี li ย่อย 10 รายการ โหนดเหล่านี้ มีการอ้างอิงโดยโค้ดแต่ไม่มีอยู่ในโครงสร้าง DOM ดังนั้นจึงถูกแยกออก

สแนปชอตฮีปเป็นวิธีหนึ่งในการระบุโหนดที่ถูกถอดออก ฮีปสแนปชอตจะแสดงให้คุณเห็น วิธีการกระจายหน่วยความจำในหมู่ออบเจ็กต์ JS และโหนด DOM ของหน้าเว็บ ณ ช่วงเวลาหนึ่งๆ

หากต้องการสร้างสแนปชอต ให้เปิดเครื่องมือสำหรับนักพัฒนาเว็บและไปที่แผงหน่วยความจำ จากนั้นเลือกฮีป ปุ่มตัวเลือก จากนั้นกดปุ่มถ่ายภาพ

ถ่ายฮีปสแนปชอต

สแนปชอตอาจใช้เวลาสักครู่ในการประมวลผลและโหลด เมื่อเสร็จแล้ว ให้เลือกจากทางซ้ายมือ (ชื่อว่าสแนปชอตฮีป)

พิมพ์ Detached ในช่องข้อความตัวกรองคลาสเพื่อค้นหาต้นไม้ DOM ที่แยกออก

การกรองโหนดที่ปลดออก

ขยายกะรัตเพื่อตรวจสอบต้นไม้ที่แยกออกจากกัน

กำลังตรวจสอบต้นไม้ที่ตัดออก

โหนดที่ไฮไลต์ด้วยสีเหลืองมีการอ้างอิงโดยตรงจากโค้ด JavaScript ไฮไลต์โหนดแล้ว สีแดงไม่มีการอ้างอิงโดยตรง พวกเขายังมีชีวิตอยู่เนื่องจากเป็นส่วนหนึ่งของโหนดสีเหลือง ต้นไม้ โดยทั่วไป คุณจะให้ความสำคัญกับโหนดสีเหลือง แก้ไขโค้ดเพื่อไม่ให้โหนดสีเหลือง มีชีวิตอยู่นานกว่าที่ควรจะเป็น และคุณก็กำจัดโหนดสีแดงที่เป็นส่วนหนึ่งของ ต้นไม้ของโหนดสีเหลือง

คลิกที่โหนดสีเหลืองเพื่อตรวจสอบเพิ่มเติม ในแผงออบเจ็กต์คุณจะเห็นข้อมูลเพิ่มเติม ข้อมูลเกี่ยวกับโค้ดที่ใช้อ้างอิง เช่น ในภาพหน้าจอด้านล่างคุณจะเห็น ว่าตัวแปร detachedTree กำลังอ้างอิงโหนด หากต้องการแก้ไขหน่วยความจำรั่วไหล จะศึกษาโค้ดที่ใช้ detachedTree และตรวจสอบว่าได้ลบการอ้างอิงไปยังโหนดแล้ว เมื่อไม่จำเป็นต้องใช้แล้ว

การตรวจสอบโหนดสีเหลือง

ระบุการรั่วไหลของหน่วยความจำฮีป JS ด้วยไทม์ไลน์การจัดสรร

ไทม์ไลน์การจัดสรรเป็นอีกเครื่องมือหนึ่งที่จะช่วยคุณติดตามการรั่วไหลของหน่วยความจำในฮีป JS

หากต้องการแสดงไทม์ไลน์การจัดสรร ให้พิจารณาโค้ดต่อไปนี้

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

ทุกครั้งที่มีการพุชปุ่มที่อ้างอิงในโค้ด สตริงที่มีอักขระ 1 ล้านตัว เพิ่มในอาร์เรย์ x แล้ว

หากต้องการบันทึกไทม์ไลน์การจัดสรร ให้เปิดเครื่องมือสำหรับนักพัฒนาเว็บและไปยังแผงโปรไฟล์ จากนั้นเลือกบันทึก ปุ่มตัวเลือกไทม์ไลน์การจัดสรร กดปุ่มเริ่ม ดำเนินการที่คุณสงสัยว่า ทำให้หน่วยความจำรั่วไหล แล้วคลิกปุ่มหยุดบันทึก (ปุ่มหยุดบันทึก) เมื่อ เท่านี้ก็เรียบร้อย

ขณะที่คุณบันทึก ให้สังเกตว่ามีแถบสีน้ำเงินแสดงอยู่ในไทม์ไลน์การจัดสรรหรือไม่ เช่น ตามภาพหน้าจอด้านล่าง

การจัดสรรใหม่

แถบสีน้ำเงินแสดงถึงการจัดสรรหน่วยความจำใหม่ การจัดสรรหน่วยความจำใหม่เหล่านี้เป็นตัวเลือกของคุณ สำหรับหน่วยความจำรั่วไหล คุณสามารถซูมแถบเพื่อกรองแผงตัวสร้างให้แสดงเฉพาะวัตถุที่ ในระหว่างช่วงเวลาที่ระบุ

ไทม์ไลน์การจัดสรรแบบซูม

ขยายออบเจ็กต์และคลิกค่าเพื่อดูรายละเอียดเพิ่มเติมเกี่ยวกับออบเจ็กต์นั้นในแผงออบเจ็กต์ สำหรับ เช่น ในภาพหน้าจอด้านล่าง ดูรายละเอียดของออบเจ็กต์ที่จัดสรรใหม่ คุณจะเห็นว่ามีการจัดสรรให้กับตัวแปร x ในขอบเขต Window

รายละเอียดออบเจ็กต์

ตรวจสอบการจัดสรรหน่วยความจำตามฟังก์ชัน

ใช้ประเภทการสุ่มตัวอย่างการจัดสรรในแผงหน่วยความจำเพื่อดูการจัดสรรหน่วยความจำตามฟังก์ชัน JavaScript

เครื่องมือสร้างโปรไฟล์การจัดสรร

  1. เลือกปุ่มตัวเลือกการสุ่มตัวอย่างการจัดสรร หากมีผู้ปฏิบัติงานในหน้านั้น คุณ สามารถเลือกเป้าหมายนั้นเป็นเป้าหมายการทำโปรไฟล์ได้โดยใช้เมนูแบบเลื่อนลงข้างปุ่ม Start
  2. กดปุ่มเริ่ม
  3. ดำเนินการในหน้าเว็บที่ต้องการตรวจสอบ
  4. กดปุ่มหยุดเมื่อคุณดำเนินการทั้งหมดแล้ว

เครื่องมือสำหรับนักพัฒนาเว็บแสดงรายละเอียดการจัดสรรหน่วยความจำตามฟังก์ชัน มุมมองเริ่มต้นคือหนัก (ด้านล่าง) ขึ้น) ซึ่งแสดงฟังก์ชันที่จัดสรรหน่วยความจำมากที่สุดไว้ที่ด้านบน

โปรไฟล์การจัดสรร

พบขยะที่เก็บขยะบ่อยๆ

หากดูเหมือนว่าหน้าเว็บหยุดชั่วคราวบ่อยครั้ง แสดงว่าคุณอาจมีปัญหาเรื่องขยะ

คุณสามารถใช้ตัวจัดการงานของ Chrome หรือการบันทึกหน่วยความจำของไทม์ไลน์เพื่อดูไฟล์ขยะที่พบบ่อย คอลเล็กชัน ในตัวจัดการงาน หน่วยความจำหรือหน่วยความจำ JavaScript ที่เพิ่มขึ้นและลดลงบ่อยครั้ง ค่าต่างๆ หมายถึงการเก็บขยะบ่อยๆ ในการบันทึกไทม์ไลน์ ขึ้นและลงบ่อยครั้ง กราฟฮีปของ JS หรือกราฟจำนวนโหนดระบุคอลเล็กชันขยะบ่อยครั้ง

เมื่อทราบปัญหาแล้ว คุณสามารถใช้การบันทึกไทม์ไลน์การจัดสรรเพื่อค้นหาว่า มีการจัดสรรหน่วยความจำและฟังก์ชันใดที่ทำให้เกิดการจัดสรร