ส่วนนี้อธิบายคำศัพท์ทั่วไปที่ใช้ในการวิเคราะห์หน่วยความจำ และใช้ได้กับเครื่องมือต่างๆ ในการจัดทำโปรไฟล์หน่วยความจำสำหรับภาษาต่างๆ
คําศัพท์และแนวคิดที่อธิบายไว้ที่นี่หมายถึงเครื่องมือตรวจสอบกองขยะของเครื่องมือสําหรับนักพัฒนาเว็บใน 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 หากวัตถุเกือบทั้งหมดในประเภทเดียวกันอยู่ห่างจากกล้องในระยะเดียวกัน แต่มีวัตถุเพียงไม่กี่รายการที่อยู่ห่างจากกล้องในระยะที่ไกลกว่า ก็เป็นสิ่งที่ควรตรวจสอบ
ผู้ควบคุม
ออบเจ็กต์ Dominator ประกอบด้วยโครงสร้างต้นไม้เนื่องจากแต่ละออบเจ็กต์มี Dominator เพียงรายการเดียว โดมิเนเตอร์ของออบเจ็กต์อาจไม่มีการอ้างอิงโดยตรงไปยังออบเจ็กต์ที่โดมิเนต กล่าวคือ ต้นไม้ของโดมิเนเตอร์ไม่ใช่ต้นไม้ที่ครอบคลุมของกราฟ
ในแผนภาพต่อไปนี้
- โหนด 1 ควบคุมโหนด 2
- โหนด 2 ควบคุมโหนด 3, 4 และ 6
- โหนด 3 ควบคุมโหนด 5
- โหนด 5 ครอบงำโหนด 8
- โหนด 6 ครอบงำโหนด 7
ในตัวอย่างต่อไปนี้ โหนด #3
เป็นผู้ควบคุม #10
แต่ #7
ก็มีอยู่ในเส้นทางแบบง่ายทุกเส้นทางจาก 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 อีกต่อไป แต่การลืมยกเลิกการระงับไฟล์กลุ่มเดียวจะระงับทั้งกลุ่มและไฟล์กลุ่มที่เกี่ยวข้อง