คำศัพท์เกี่ยวกับหน่วยความจำ

Meggin Kearney
Meggin Kearney

ส่วนนี้อธิบายคำศัพท์ทั่วไปที่ใช้ในการวิเคราะห์หน่วยความจำ และใช้ได้กับเครื่องมือต่างๆ ในการจัดทำโปรไฟล์หน่วยความจำสำหรับภาษาต่างๆ

คําศัพท์และแนวคิดที่อธิบายไว้ที่นี่หมายถึงเครื่องมือตรวจสอบกองขยะของเครื่องมือสําหรับนักพัฒนาเว็บใน Chrome หากคุณเคยใช้ Java, .NET หรือเครื่องมือวิเคราะห์หน่วยความจำอื่นๆ มาก่อน บทความนี้อาจช่วยทบทวนความรู้ได้

ขนาดของวัตถุ

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

การนำเสนอความทรงจำด้วยภาพ

ออบเจ็กต์สามารถเก็บหน่วยความจำได้ 2 วิธีดังนี้

  • โดยตรงจากออบเจ็กต์
  • โดยนัยคือมีการเก็บข้อมูลอ้างอิงไปยังออบเจ็กต์อื่นๆ และป้องกันไม่ให้ตัวเก็บขยะ (GC) กำจัดออบเจ็กต์เหล่านั้นโดยอัตโนมัติ

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

คอลัมน์ขนาดแบบตื้นและแบบคงไว้ในแผงหน่วยความจํา

ขนาดระดับออบเจ็กต์

ค่านี้คือขนาดหน่วยความจำที่ออบเจ็กต์ใช้

ออบเจ็กต์ JavaScript ทั่วไปมีการจองหน่วยความจำบางส่วนไว้สำหรับคำอธิบายและสำหรับจัดเก็บค่าทันที โดยปกติแล้ว มีเพียงอาร์เรย์และสตริงเท่านั้นที่มีขนาดแบบตื้นที่สำคัญ อย่างไรก็ตาม สตริงและอาร์เรย์ภายนอกมักจะมีที่จัดเก็บหลักอยู่ในหน่วยความจำของโปรแกรมแสดงผล โดยจะแสดงเฉพาะออบเจ็กต์ Wrapper ขนาดเล็กในกองขยะ JavaScript

หน่วยความจําของโปรแกรมแสดงผลคือหน่วยความจําทั้งหมดของกระบวนการที่แสดงผลหน้าเว็บที่ตรวจสอบ: หน่วยความจําเนทีฟ + หน่วยความจํากองกอง JS ของหน้าเว็บ + หน่วยความจํากองกอง JS ของผู้ปฏิบัติงานเฉพาะทั้งหมดที่หน้าเว็บเริ่มต้น อย่างไรก็ตาม ออบเจ็กต์ขนาดเล็กก็สามารถเก็บหน่วยความจำจํานวนมากได้โดยอ้อม โดยการป้องกันการที่กระบวนการเก็บขยะอัตโนมัติจะนําออบเจ็กต์อื่นๆ ออก

ขนาดที่คงไว้

ค่านี้คือขนาดหน่วยความจำที่ว่างขึ้นเมื่อลบออบเจ็กต์พร้อมกับออบเจ็กต์ที่เกี่ยวข้องซึ่งทำให้เข้าถึงจากรูท GC ไม่ได้

รูท GC ประกอบด้วยแฮนเดิลที่สร้าง (ทั้งแบบภายในหรือแบบภายนอก) เมื่อทำการอ้างอิงจากโค้ดเนทีฟไปยังออบเจ็กต์ JavaScript นอก V8 แฮนเดิลทั้งหมดดังกล่าวจะอยู่ในสแนปชอตกองที่อยู่ภายใต้รูท GC > ขอบเขตแฮนเดิล และรูท GC > แฮนเดิลส่วนกลาง การอธิบายแฮนเดิลในเอกสารประกอบนี้โดยไม่เจาะลึกรายละเอียดการใช้งานเบราว์เซอร์อาจทําให้สับสน คุณไม่จำเป็นต้องกังวลเกี่ยวกับทั้งรูท GC และตัวแฮนเดิล

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

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

กราฟหน่วยความจำเริ่มต้นด้วยรูท ซึ่งอาจเป็นออบเจ็กต์ window ของเบราว์เซอร์หรือออบเจ็กต์ Global ของโมดูล Node.js คุณไม่สามารถควบคุมวิธีจัดเก็บออบเจ็กต์รูทนี้ใน GC

ควบคุมออบเจ็กต์รูทไม่ได้

ทุกอย่างที่เข้าถึงจากรูทไม่ได้จะได้รับ GC

ต้นไม้ของออบเจ็กต์ที่เก็บรักษา

กองคือเครือข่ายของวัตถุที่เชื่อมต่อกัน ในวงการคณิตศาสตร์ โครงสร้างนี้เรียกว่ากราฟหรือกราฟความทรงจำ กราฟสร้างขึ้นจากโหนดที่เชื่อมต่อกันด้วยขอบ ซึ่งทั้ง 2 อย่างมีป้ายกำกับ

  • โหนด (หรือออบเจ็กต์) จะมีการติดป้ายกำกับโดยใช้ชื่อของฟังก์ชันคอนสตรัคเตอร์ที่ใช้สร้างโหนด
  • ขอบจะติดป้ายกำกับโดยใช้ชื่อพร็อพเพอร์ตี้

ดูวิธีบันทึกโปรไฟล์โดยใช้ Heap Profiler สิ่งที่น่าสนใจบางอย่างที่เราเห็นในการบันทึก Heap Profiler ต่อไปนี้ ได้แก่ ระยะทาง: ระยะทางจากรูท GC หากวัตถุเกือบทั้งหมดในประเภทเดียวกันอยู่ห่างจากกล้องในระยะเดียวกัน แต่มีวัตถุเพียงไม่กี่รายการที่อยู่ห่างจากกล้องมากกว่า กรณีนี้ควรตรวจสอบ

ตัวอย่างระยะทางจากรูท

ผู้ควบคุม

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

ในแผนภาพต่อไปนี้

  • โหนด 1 ควบคุมโหนด 2
  • โหนด 2 ควบคุมโหนด 3, 4 และ 6
  • โหนด 3 ควบคุมโหนด 5
  • โหนด 5 ครอบงำโหนด 8
  • โหนด 6 ครอบงำโหนด 7

โครงสร้างแผนผังโดมิเนเตอร์

ในตัวอย่างต่อไปนี้ โหนด #7, #3 และ GC เป็นผู้ควบคุมของ #10 เนื่องจากมีอยู่ในเส้นทางทุกเส้นทางจากรูท (GC) ไปยัง #10 กล่าวโดยละเอียดคือ #7 เป็นโดมิเนเตอร์โดยตรงของ #10 เนื่องจากเป็นโดมิเนเตอร์ที่ใกล้ที่สุดในเส้นทางจาก GC ไปยัง #10

ภาพโดมิเนเตอร์แบบเคลื่อนไหว

ข้อมูลเฉพาะของ V8

เมื่อทำโปรไฟล์หน่วยความจำ การทำความเข้าใจสาเหตุที่ภาพรวมกองมีลักษณะหนึ่งๆ ย่อมมีประโยชน์ ส่วนนี้จะอธิบายหัวข้อที่เกี่ยวข้องกับหน่วยความจําบางหัวข้อซึ่งเกี่ยวข้องกับเครื่องเสมือน JavaScript ของ V8 (V8 VM หรือ VM) โดยเฉพาะ

การนําเสนอออบเจ็กต์ JavaScript

ประเภทพื้นฐานมี 3 ประเภท ได้แก่

  • ตัวเลข (เช่น 3.14159..)
  • บูลีน (จริงหรือเท็จ)
  • สตริง (เช่น 'Werner Heisenberg')

ไม่สามารถอ้างอิงค่าอื่นๆ และจะเป็นใบไม้หรือโหนดสิ้นสุดเสมอ

ตัวเลขสามารถจัดเก็บในรูปแบบใดรูปแบบหนึ่งต่อไปนี้

  • ค่าจำนวนเต็ม 31 บิตแบบทันทีที่เรียกว่าจำนวนเต็มขนาดเล็ก (SMIs) หรือ
  • ออบเจ็กต์กองซึ่งเรียกว่าตัวเลขกอง ตัวเลขกองใช้สำหรับจัดเก็บค่าที่ไม่พอดีกับรูปแบบ SMI เช่น double หรือเมื่อต้องบรรจุค่า เช่น การตั้งค่าพร็อพเพอร์ตี้ในค่า

สตริงจะจัดเก็บไว้ในตำแหน่งใดตำแหน่งหนึ่งต่อไปนี้

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

ระบบจะจัดสรรหน่วยความจำสำหรับออบเจ็กต์ JavaScript ใหม่จากฮีป JavaScript โดยเฉพาะ (หรือฮีป VM) ออบเจ็กต์เหล่านี้ได้รับการจัดการโดยเครื่องมือเก็บขยะของ V8 และจะยังคงอยู่ตราบใดที่มีข้อมูลอ้างอิงอย่างน้อย 1 รายการที่อ้างอิงถึง

ออบเจ็กต์เนทีฟคือทุกอย่างที่ไม่ใช่ในกองขยะ JavaScript ออบเจ็กต์เนทีฟต่างจากออบเจ็กต์ฮีปตรงที่ตัวเก็บขยะ V8 จะไม่จัดการตลอดอายุการใช้งาน และเข้าถึงได้จาก JavaScript โดยใช้ออบเจ็กต์ Wrapper ของ JavaScript เท่านั้น

สตริง Cons คือออบเจ็กต์ที่ประกอบด้วยคู่สตริงที่จัดเก็บไว้แล้วรวมเข้าด้วยกัน และเป็นผลลัพธ์ของการต่อสตริง การรวมเนื้อหา cons string จะเกิดขึ้นเมื่อจําเป็นเท่านั้น ตัวอย่างเช่น เมื่อต้องสร้างสตริงย่อยของสตริงที่รวม

เช่น หากคุณต่อสตริง a และ b คุณจะได้รับสตริง (a, b) ซึ่งแสดงผลลัพธ์ของการต่อสตริง หากต่อท้าย d กับผลลัพธ์นั้นในภายหลัง คุณจะได้รับสตริงคอนสอีกรายการหนึ่ง ((a, b), d)

อาร์เรย์ - อาร์เรย์คือออบเจ็กต์ที่มีคีย์ตัวเลข ซึ่งใช้ใน VM V8 กันอย่างแพร่หลายเพื่อจัดเก็บข้อมูลจำนวนมาก ชุดคู่คีย์-ค่าที่ใช้เหมือนพจนานุกรมจะได้รับการสำรองข้อมูลโดยอาร์เรย์

ออบเจ็กต์ JavaScript ทั่วไปอาจเป็นอาร์เรย์ประเภทใดประเภทหนึ่งต่อไปนี้ซึ่งใช้สำหรับจัดเก็บ

  • พร็อพเพอร์ตี้ที่มีชื่อ และ
  • องค์ประกอบตัวเลข

ในกรณีที่มีพร็อพเพอร์ตี้เพียงไม่กี่รายการ ระบบจะจัดเก็บพร็อพเพอร์ตี้เหล่านั้นไว้ในออบเจ็กต์ JavaScript โดยตรง

แผนที่ - ออบเจ็กต์ที่อธิบายประเภทของออบเจ็กต์และเลย์เอาต์ เช่น ระบบจะใช้แผนที่เพื่ออธิบายลําดับชั้นของออบเจ็กต์โดยนัยสําหรับการเข้าถึงพร็อพเพอร์ตี้อย่างรวดเร็ว

กลุ่มออบเจ็กต์

กลุ่มออบเจ็กต์เนทีฟแต่ละกลุ่มประกอบด้วยออบเจ็กต์ที่อ้างอิงซึ่งกันและกัน ตัวอย่างเช่น พิจารณาซับต้นไม้ DOM ที่ทุกโหนดมีลิงก์ไปยังโหนดหลัก รวมถึงลิงก์ไปยังโหนดย่อยและโหนดพี่น้องถัดไป เพื่อสร้างกราฟที่เชื่อมต่อกัน โปรดทราบว่าออบเจ็กต์เนทีฟจะไม่แสดงในกอง JavaScript ซึ่งเป็นเหตุผลที่ออบเจ็กต์เหล่านี้มีขนาดเป็น 0 ระบบจะสร้างออบเจ็กต์ Wrapper แทน

ออบเจ็กต์ Wrapper แต่ละรายการมีการอ้างอิงถึงออบเจ็กต์เนทีฟที่เกี่ยวข้องสำหรับการเปลี่ยนเส้นทางคําสั่งไปยังออบเจ็กต์นั้น กลุ่มออบเจ็กต์จะเก็บออบเจ็กต์ Wrapper ไว้ อย่างไรก็ตาม การดำเนินการนี้จะไม่สร้างวงจรที่รวบรวมไม่ได้ เนื่องจาก GC ฉลาดพอที่จะปล่อยกลุ่มออบเจ็กต์ที่ไม่มีการอ้างอิงถึง Wrapper อีกต่อไป แต่การลืมยกเลิกการบับเบิ้ลรายการเดียวจะระงับทั้งกลุ่มและบับเบิ้ลที่เกี่ยวข้อง