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

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

สรุป

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

ภาพรวม

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

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

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

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

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

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

กุญแจสำคัญในที่นี้คือการใช้โมเดล 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 บางรายการยังคงอ้างอิงโหนดนั้น โหนด 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. เลือกปุ่มตัวเลือกการสุ่มตัวอย่างการจัดสรร หากมีผู้ปฏิบัติงานในหน้านั้น คุณจะเลือกพนักงานดังกล่าวเป็นเป้าหมายการทำโปรไฟล์ได้โดยใช้เมนูแบบเลื่อนลงข้างปุ่มเริ่มต้น
  2. กดปุ่มเริ่ม
  3. ดำเนินการในหน้าเว็บที่ต้องการตรวจสอบ
  4. กดปุ่มหยุดเมื่อคุณดำเนินการทั้งหมดแล้ว

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

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

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

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

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

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