บทนำ
แม้ว่า JavaScript จะใช้การเก็บขยะเพื่อการจัดการหน่วยความจําอัตโนมัติ แต่ก็ไม่ได้ใช้แทนการจัดการหน่วยความจําที่มีประสิทธิภาพในแอปพลิเคชัน แอปพลิเคชัน JavaScript ประสบปัญหาเกี่ยวกับหน่วยความจำเช่นเดียวกับแอปพลิเคชันเนทีฟ เช่น หน่วยความจำรั่วไหลและระบบทำงานหนักเกินความจำเป็น แต่แอปพลิเคชันเหล่านี้ยังต้องจัดการกับการหยุดชั่วคราวของการเก็บขยะด้วย แอปพลิเคชันขนาดใหญ่อย่าง Gmail ก็พบปัญหาเดียวกันกับแอปพลิเคชันขนาดเล็ก อ่านต่อเพื่อดูวิธีที่ทีม Gmail ใช้เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome เพื่อระบุ แยก และแก้ไขปัญหาเกี่ยวกับหน่วยความจำ
เซสชัน Google I/O 2013
เราได้นำเสนอเนื้อหานี้ในงาน Google I/O 2013 ดูวิดีโอด้านล่าง
Gmail เราพบปัญหา
ทีม Gmail กำลังประสบปัญหาร้ายแรง เราได้ยินเรื่องราวต่างๆ เกี่ยวกับแท็บ Gmail ที่ใช้หน่วยความจำหลายกิกะไบต์ในแล็ปท็อปและเดสก์ท็อปที่มีทรัพยากรจำกัดบ่อยขึ้นเรื่อยๆ ซึ่งมักจะจบลงด้วยการทำให้เบราว์เซอร์ทั้งตัวหยุดทำงาน เรื่องราวเกี่ยวกับ CPU ที่ทำงานเต็ม 100%, แอปไม่ตอบสนอง และแท็บ Chrome เศร้า ("ตายแล้ว เพื่อน") ทีมไม่ทราบว่าจะเริ่มวินิจฉัยปัญหาได้อย่างไร ซ้ำร้ายกว่านั้นยังแก้ปัญหาไม่ได้ ทีมดังกล่าวไม่ทราบว่าการแพร่กระจายของปัญหามีมากน้อยเพียงใด และเครื่องมือที่มีอยู่ไม่สามารถปรับขนาดให้เหมาะกับแอปพลิเคชันขนาดใหญ่ได้ ทีมนี้ร่วมมือกับทีม Chrome เพื่อพัฒนาเทคนิคใหม่ๆ ในการจัดลำดับความสำคัญของปัญหาเกี่ยวกับหน่วยความจำ ปรับปรุงเครื่องมือที่มีอยู่ และเปิดใช้การเก็บรวบรวมข้อมูลหน่วยความจำจากภาคสนาม แต่ก่อนที่จะพูดถึงเครื่องมือ เรามาพูดถึงพื้นฐานของการจัดการหน่วยความจําของ JavaScript ก่อน
ข้อมูลเบื้องต้นเกี่ยวกับการจัดการหน่วยความจำ
คุณต้องเข้าใจพื้นฐานก่อนจึงจะจัดการหน่วยความจำใน JavaScript ได้อย่างมีประสิทธิภาพ ส่วนนี้จะกล่าวถึงประเภทพื้นฐาน กราฟออบเจ็กต์ และให้คำจำกัดความของหน่วยความจำที่เพิ่มขึ้นโดยทั่วไปและการรั่วไหลของหน่วยความจำใน JavaScript หน่วยความจําใน JavaScript สามารถจําลองเป็นกราฟได้ ด้วยเหตุนี้ ทฤษฎีกราฟจึงมีส่วนในการจัดการหน่วยความจําของ JavaScript และ เครื่องมือตรวจสอบกอง
ประเภทพื้นฐาน
JavaScript มีประเภทพื้นฐาน 3 ประเภท ได้แก่
- ตัวเลข (เช่น 4, 3.14159)
- บูลีน (จริงหรือเท็จ)
- สตริง ("Hello World")
ประเภทพื้นฐานเหล่านี้ไม่สามารถอ้างอิงค่าอื่นๆ ได้ ในกราฟออบเจ็กต์ ค่าเหล่านี้จะเป็นโหนดใบหรือโหนดสิ้นสุดเสมอ ซึ่งหมายความว่าจะไม่มีขอบขาออก
คอนเทนเนอร์มีเพียงประเภทเดียวเท่านั้น ได้แก่ ออบเจ็กต์ ใน JavaScript ออบเจ็กต์คืออาร์เรย์ Associative ออบเจ็กต์ที่ไม่ใช่ค่าว่างคือโหนดภายในที่มีขอบขาออกไปยังค่าอื่นๆ (โหนด)
อาร์เรย์ล่ะ
อาร์เรย์ใน JavaScript จริงๆ แล้วคือออบเจ็กต์ที่มีคีย์ตัวเลข นี่เป็นวิธีอธิบายแบบง่าย เนื่องจากรันไทม์ JavaScript จะเพิ่มประสิทธิภาพออบเจ็กต์ที่คล้ายกับอาร์เรย์และแสดงเป็นอาร์เรย์ในเบื้องหลัง
คำศัพท์
- ค่า - อินสแตนซ์ของประเภทพื้นฐาน ออบเจ็กต์ อาร์เรย์ ฯลฯ
- ตัวแปร - ชื่อที่อ้างอิงค่า
- พร็อพเพอร์ตี้ - ชื่อในออบเจ็กต์ที่อ้างอิงค่า
กราฟออบเจ็กต์
ค่าทั้งหมดใน JavaScript เป็นส่วนหนึ่งของกราฟออบเจ็กต์ กราฟจะเริ่มต้นด้วยรูท เช่น ออบเจ็กต์หน้าต่าง คุณไม่สามารถควบคุมอายุการใช้งานของรูท GC ได้ เนื่องจากเบราว์เซอร์เป็นผู้สร้างและทำลายรูท GC เมื่อระบบยกเลิกการโหลดหน้าเว็บ ตัวแปรส่วนกลางคือพร็อพเพอร์ตี้ในหน้าต่าง
เมื่อใดที่ค่าจะกลายเป็นขยะ
ค่าจะกลายเป็นขยะเมื่อไม่มีเส้นทางจากรูทไปยังค่า กล่าวคือ เริ่มต้นที่รูทและค้นหาพร็อพเพอร์ตี้และตัวแปรออบเจ็กต์ทั้งหมดที่ยังมีอยู่ใน สแต็กเฟรมอย่างละเอียด แต่หาค่าไม่ได้ แสดงว่าค่าดังกล่าวกลายเป็นขยะ
หน่วยความจํารั่วไหลใน JavaScript คืออะไร
ปัญหาหน่วยความจำรั่วใน JavaScript มักเกิดขึ้นเมื่อมีโหนด DOM ที่เข้าถึงได้จากต้นไม้ DOM ของหน้า แต่ออบเจ็กต์ JavaScript ยังคงอ้างอิงอยู่ แม้ว่าเบราว์เซอร์สมัยใหม่จะทําให้การสร้างข้อมูลรั่วโดยไม่ตั้งใจนั้นยากขึ้น แต่ก็ยังง่ายกว่าที่คิด สมมติว่าคุณเพิ่มองค์ประกอบต่อท้ายแผนผัง DOM ดังนี้
email.message = document.createElement("div");
displayList.appendChild(email.message);
และต่อมาคุณนําองค์ประกอบออกจากรายการที่แสดง
displayList.removeAllChildren();
ตราบใดที่ email
ยังคงอยู่ ระบบจะไม่นำองค์ประกอบ DOM ที่ข้อความอ้างอิงออก แม้ว่าตอนนี้จะแยกออกจากต้นไม้ DOM ของหน้าแล้วก็ตาม
การเพิ่มขนาดคืออะไร
หน้าเว็บมีขนาดใหญ่เกินเหตุเมื่อคุณใช้หน่วยความจํามากกว่าที่จําเป็นเพื่อให้หน้าเว็บมีความเร็วสูงสุด การรั่วไหลของหน่วยความจํายังทําให้เกิดความล่าช้าโดยอ้อมด้วย แต่ไม่ได้เกิดจากการออกแบบ แคชแอปพลิเคชันที่ไม่มีขีดจำกัดขนาดเป็นสาเหตุที่พบบ่อยของหน่วยความจำที่เพิ่มขึ้น นอกจากนี้ หน้าเว็บอาจมีขนาดเพิ่มขึ้นเนื่องจากข้อมูลโฮสต์ เช่น ข้อมูลพิกเซลที่โหลดจากรูปภาพ
การเก็บขยะคืออะไร
การเก็บขยะเป็นวิธีเรียกคืนหน่วยความจําใน JavaScript เบราว์เซอร์จะเป็นผู้ตัดสินใจว่าจะใช้หรือไม่ ในระหว่างการเก็บรวบรวม ระบบจะระงับการเรียกใช้สคริปต์ทั้งหมดในหน้าเว็บขณะที่ค้นพบค่าปัจจุบันโดยการเรียกใช้กราฟออบเจ็กต์โดยเริ่มจากรูท GC ระบบจะจัดประเภทค่าทั้งหมดที่เข้าถึงไม่ได้ว่าเป็นขยะ เครื่องมือจัดการหน่วยความจําจะเรียกคืนหน่วยความจําสําหรับค่าที่ไม่เป็นระเบียบ
รายละเอียดเกี่ยวกับเครื่องมือเก็บขยะ V8
มาดูรายละเอียดเกี่ยวกับเครื่องมือเก็บขยะ V8 กันเพื่อทําความเข้าใจเพิ่มเติมเกี่ยวกับวิธีการทำงานของการเก็บขยะ V8 ใช้เครื่องมือรวบรวมข้อมูลตามรุ่น หน่วยความจําแบ่งออกเป็น 2 รุ่น ได้แก่ รุ่นเก่าและรุ่นใหม่ การจัดสรรและการรวบรวมภายในรุ่นที่อายุน้อยนั้นรวดเร็วและเกิดขึ้นบ่อยครั้ง การจัดสรรและการรวบรวมภายในรุ่นเก่าจะช้าลงและเกิดขึ้นน้อยลง
ผู้สะสมรุ่นต่างๆ
V8 ใช้เครื่องมือรวบรวมข้อมูล 2 รุ่น อายุของค่าคือจํานวนไบต์ที่จัดสรรนับตั้งแต่มีการจัดสรร ในทางปฏิบัติ อายุของค่ามักจะประมาณจากจํานวนคอลเล็กชันรุ่นเยาว์ที่ยังคงอยู่ หลังจากค่ามีอายุมากพอแล้ว ระบบจะจัดให้ค่าดังกล่าวอยู่ในรุ่นเก่า
ในทางปฏิบัติ ค่าที่จัดสรรใหม่จะมีอายุไม่นาน การศึกษาโปรแกรม Smalltalk พบว่ามีเพียง 7% ของค่าที่ยังคงอยู่หลังจากการรวบรวมรุ่นเยาว์ การศึกษาที่คล้ายกันเกี่ยวกับรันไทม์ต่างๆ พบว่าค่าที่จัดสรรใหม่โดยเฉลี่ย 90-70% ไม่เคยมีสถานะเป็นรุ่นเก่า
คนรุ่นใหม่
กองขยะรุ่นเยาว์ใน V8 จะแบ่งออกเป็น 2 พื้นที่ ได้แก่ from และ to ระบบจะจัดสรรหน่วยความจำจากพื้นที่ทำงาน "ไปยัง" การจัดสรรจะรวดเร็วมากจนกว่าพื้นที่เก็บข้อมูลจะเต็ม ซึ่งระบบจะเรียกใช้คอลเล็กชันรุ่นเยาว์ คอลเล็กชันรุ่นใหม่จะสลับพื้นที่จากและพื้นที่ถึงก่อน จากนั้นจะสแกนพื้นที่ถึงเดิม (ตอนนี้คือพื้นที่จาก) และคัดลอกค่าที่ใช้งานอยู่ทั้งหมดไปยังพื้นที่ถึงหรือเก็บค่าไว้ในรุ่นเก่า โดยทั่วไปแล้ว การเก็บรวบรวมรุ่นใหม่จะใช้เวลาประมาณ 10 มิลลิวินาที (ms)
คุณควรเข้าใจว่าการจองแต่ละครั้งที่แอปพลิเคชันดำเนินการจะทำให้พื้นที่เก็บข้อมูลใกล้หมดลงและทำให้ GC หยุดชั่วคราว นักพัฒนาเกม โปรดทราบว่าแอปพลิเคชันของคุณต้องมีการจัดสรรเป็น 0 เพื่อให้ได้เวลาเฟรม 16 มิลลิวินาที (จําเป็นเพื่อให้ได้ 60 เฟรมต่อวินาที) เนื่องจากคอลเล็กชันรุ่นใหม่รายการเดียวจะกินเวลาเฟรมส่วนใหญ่
รุ่นเก่า
กองรุ่นเก่าใน V8 ใช้อัลกอริทึมการทำเครื่องหมายและบีบอัดเพื่อรวบรวม การจัดสรรรุ่นเก่าจะเกิดขึ้นทุกครั้งที่มีการจัดสรรค่าจากรุ่นย่อยไปยังรุ่นเก่า เมื่อใดก็ตามที่มีการเก็บรวบรวมรุ่นเก่า ระบบก็จะเก็บรวบรวมรุ่นใหม่ด้วย แอปพลิเคชันจะหยุดชั่วคราวเป็นเวลา 2-3 วินาที ในทางปฏิบัติแล้ว การดำเนินการนี้ยอมรับได้เนื่องจากคอลเล็กชันรุ่นเก่ามีไม่บ่อย
สรุป GC ของ V8
การจัดการหน่วยความจําอัตโนมัติที่มีการเก็บขยะเหมาะสําหรับประสิทธิภาพของนักพัฒนาซอฟต์แวร์ แต่ทุกครั้งที่คุณจัดสรรค่า คุณจะเข้าใกล้การหยุดเก็บขยะชั่วคราวมากขึ้น การหยุดเก็บขยะชั่วคราวอาจทำให้แอปพลิเคชันทำงานขัดข้อง เมื่อเข้าใจวิธีที่ JavaScript จัดการหน่วยความจำแล้ว คุณจะทำการเลือกที่เหมาะสมสําหรับแอปพลิเคชันได้
การแก้ไข Gmail
ในช่วงปีที่ผ่านมา เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ได้รับการอัปเดตฟีเจอร์และการแก้ไขข้อบกพร่องมากมาย ซึ่งทำให้เครื่องมือนี้มีประสิทธิภาพมากขึ้นกว่าที่เคย นอกจากนี้ เบราว์เซอร์เองก็ทำการเปลี่ยนแปลงที่สำคัญใน performance.memory API ซึ่งทำให้ Gmail และแอปพลิเคชันอื่นๆ สามารถรวบรวมสถิติหน่วยความจำจากช่องได้ เมื่อใช้เครื่องมืออันยอดเยี่ยมเหล่านี้ สิ่งที่เคยดูเหมือนงานเป็นไปไม่ได้ก็กลายเป็นเกมการติดตามหาผู้ร้ายที่น่าตื่นเต้น
เครื่องมือและเทคนิค
ข้อมูลภาคสนามและ performance.memory API
ตั้งแต่ Chrome เวอร์ชัน 22 ระบบจะเปิดใช้ performance.memory API โดยค่าเริ่มต้น สําหรับแอปพลิเคชันที่ทำงานมาอย่างยาวนาน เช่น Gmail ข้อมูลจากผู้ใช้จริงมีคุณค่าอย่างยิ่ง ข้อมูลนี้ช่วยให้เราแยกความแตกต่างระหว่างผู้ใช้ขั้นสูง ซึ่งใช้เวลา 8-16 ชั่วโมงต่อวันใน Gmail และได้รับข้อความหลายร้อยฉบับต่อวัน กับผู้ใช้ทั่วไปที่ใช้ Gmail เพียงไม่กี่นาทีต่อวันและได้รับข้อความประมาณ 12 ฉบับต่อสัปดาห์
API นี้จะแสดงผลข้อมูล 3 รายการ ได้แก่
- jsHeapSizeLimit - จํานวนหน่วยความจํา (เป็นไบต์) ที่จำกัดให้กับกองข้อมูล JavaScript
- totalJSHeapSize - จํานวนหน่วยความจํา (เป็นไบต์) ที่กองขยะ JavaScript ที่จัดสรรไว้ รวมถึงพื้นที่ว่าง
- usedJSHeapSize - จํานวนหน่วยความจํา (เป็นไบต์) ที่ใช้งานอยู่ในปัจจุบัน
สิ่งที่ควรทราบคือ API จะแสดงค่าหน่วยความจําสําหรับกระบวนการทั้งหมดของ Chrome แม้ว่าจะไม่ใช่โหมดเริ่มต้น แต่ Chrome อาจเปิดแท็บหลายแท็บในกระบวนการแสดงผลเดียวกันได้ในบางกรณี ซึ่งหมายความว่าค่าที่ performance.memory แสดงอาจมีการอ้างอิงหน่วยความจําของแท็บเบราว์เซอร์อื่นๆ นอกเหนือจากแท็บที่มีแอปของคุณ
การวัดหน่วยความจําในวงกว้าง
Gmail เครื่องมือวัด JavaScript เพื่อใช้ performance.memory API เพื่อรวบรวมข้อมูลหน่วยความจําประมาณ 1 ครั้งทุก 30 นาที เนื่องจากผู้ใช้ Gmail จำนวนมากเปิดแอปไว้หลายวัน ทีมจึงติดตามปริมาณหน่วยความจำที่เพิ่มขึ้นเมื่อเวลาผ่านไป รวมถึงสถิติเกี่ยวกับพื้นที่หน่วยความจำโดยรวมได้ ภายในไม่กี่วันหลังจากติดตั้งเครื่องมือวัดใน Gmail เพื่อรวบรวมข้อมูลหน่วยความจำจากตัวอย่างผู้ใช้แบบสุ่ม ทีมมีข้อมูลเพียงพอที่จะเข้าใจว่าปัญหาหน่วยความจำเกิดขึ้นในหมู่ผู้ใช้ทั่วไปมากน้อยเพียงใด พวกเขากําหนดเส้นฐานและใช้สตรีมข้อมูลที่เข้ามาเพื่อติดตามความคืบหน้าตามเป้าหมายในการลดการใช้หน่วยความจํา ในที่สุดแล้ว ระบบจะใช้ข้อมูลนี้เพื่อตรวจหาการถดถอยของหน่วยความจําด้วย
นอกจากวัตถุประสงค์ในการติดตามแล้ว การวัดผลในพื้นที่ยังให้ข้อมูลเชิงลึกที่เป็นประโยชน์เกี่ยวกับความสัมพันธ์ระหว่างพื้นที่หน่วยความจำกับประสิทธิภาพของแอปพลิเคชันด้วย ตรงกันข้ามกับความเชื่อที่ว่า "ยิ่งมีหน่วยความจำมาก ประสิทธิภาพก็จะยิ่งดีขึ้น" ทีม Gmail พบว่ายิ่งมีการใช้หน่วยความจำมากเท่าใด เวลาในการตอบสนองของการดำเนินการทั่วไปใน Gmail ก็จะยิ่งนานขึ้นเท่านั้น ข้อมูลนี้ช่วยให้ทีมมีแรงจูงใจมากขึ้นกว่าที่เคยในการควบคุมการใช้หน่วยความจํา
ระบุปัญหาเกี่ยวกับหน่วยความจำด้วยไทม์ไลน์ของเครื่องมือสำหรับนักพัฒนาเว็บ
ขั้นตอนแรกในการแก้ปัญหาด้านประสิทธิภาพคือการพิสูจน์ว่ามีปัญหาเกิดขึ้น สร้างการทดสอบที่ทําให้เกิดปัญหาซ้ำได้ และวัดค่าพื้นฐานของปัญหา หากไม่มีโปรแกรมที่ทําซ้ำได้ คุณจะวัดปัญหาได้อย่างน่าเชื่อถือไม่ได้ หากไม่มีการวัดพื้นฐาน คุณจะไม่ทราบว่าได้ปรับปรุงประสิทธิภาพมากน้อยเพียงใด
แผงไทม์ไลน์ของเครื่องมือสำหรับนักพัฒนาเว็บเหมาะอย่างยิ่งในการพิสูจน์ว่ามีปัญหาเกิดขึ้น ซึ่งจะแสดงภาพรวมที่สมบูรณ์เกี่ยวกับเวลาที่ใช้ในการโหลดและโต้ตอบกับเว็บแอปหรือหน้าเว็บ เหตุการณ์ทั้งหมดตั้งแต่การโหลดทรัพยากรไปจนถึงการแยกวิเคราะห์ JavaScript, การคํานวณสไตล์, การหยุดเก็บขยะชั่วคราว และการวาดภาพใหม่จะแสดงเป็นผังไทม์ไลน์ แผงไทม์ไลน์ยังมีโหมดหน่วยความจําเพื่อวัตถุประสงค์ในการตรวจสอบปัญหาหน่วยความจํา ซึ่งจะติดตามหน่วยความจําทั้งหมดที่จัดสรร จํานวนโหนด DOM จํานวนออบเจ็กต์หน้าต่าง และจํานวน Listener เหตุการณ์ที่จัดสรร
พิสูจน์ว่ามีปัญหาเกิดขึ้น
เริ่มต้นด้วยการระบุลำดับการดำเนินการที่คุณสงสัยว่ามีการสูญเสียหน่วยความจำ เริ่มบันทึกไทม์ไลน์ แล้วทำตามลำดับการดำเนินการ ใช้ปุ่มถังขยะที่ด้านล่างเพื่อบังคับให้รวบรวมขยะทั้งหมด หากหลังจากทำซ้ำ 2-3 ครั้ง คุณเห็นกราฟรูปฟันเลื่อย แสดงว่าคุณกําลังจัดสรรออบเจ็กต์ที่มีอายุสั้นจํานวนมาก แต่หากลำดับการดำเนินการไม่ได้คาดหวังว่าจะส่งผลให้มีหน่วยความจำที่เก็บไว้ และจํานวนโหนด DOM ไม่ได้ลดลงกลับไปยังเส้นฐานที่คุณเริ่ม คุณก็มีเหตุผลที่ดีที่จะสงสัยว่ามีการรั่วไหล
เมื่อยืนยันแล้วว่ามีปัญหาเกิดขึ้นแล้ว คุณสามารถรับความช่วยเหลือในการระบุแหล่งที่มาของปัญหาได้จากเครื่องมือวิเคราะห์กองขยะของ DevTools
การค้นหาหน่วยความจําที่รั่วไหลด้วยเครื่องมือสร้างโปรไฟล์ฮีปของ DevTools
แผงเครื่องมือวิเคราะห์มีทั้งเครื่องมือวิเคราะห์ CPU และเครื่องมือวิเคราะห์ฮีป โปรไฟล์กองขยะจะทํางานโดยการจับภาพกราฟออบเจ็กต์ ระบบจะเก็บขยะทั้งรุ่นเก่าและรุ่นใหม่ก่อนที่จะจับภาพ กล่าวคือ คุณจะเห็นเฉพาะค่าที่มีอยู่เมื่อถ่ายภาพหน้าจอ
เครื่องมือวิเคราะห์ฮีปมีฟังก์ชันการทำงานมากมายเกินกว่าที่จะอธิบายได้ครบถ้วนในบทความนี้ แต่คุณสามารถดูเอกสารประกอบโดยละเอียดได้ในเว็บไซต์ของนักพัฒนาซอฟต์แวร์ Chrome เราจะมุ่งเน้นที่เครื่องมือสร้างโปรไฟล์การจัดสรรฮีป
การใช้เครื่องมือสร้างโปรไฟล์การจัดสรรฮีป
เครื่องมือวิเคราะห์การจัดสรรฮีปจะรวมข้อมูลภาพรวมโดยละเอียดของเครื่องมือวิเคราะห์ฮีปเข้ากับการอัปเดตและการติดตามที่เพิ่มขึ้นของแผงไทม์ไลน์ เปิดแผงโปรไฟล์ เริ่มโปรไฟล์บันทึกการจัดสรรฮีป ดำเนินการตามลำดับ แล้วหยุดการบันทึกเพื่อการวิเคราะห์ เครื่องมือวิเคราะห์การจัดสรรหน่วยความจำจะจับภาพรวมของกองเป็นระยะๆ ตลอดการบันทึก (บ่อยครั้งทุกๆ 50 มิลลิวินาที) และจับภาพรวมสุดท้ายเมื่อสิ้นสุดการบันทึก
แถบด้านบนจะระบุเมื่อพบออบเจ็กต์ใหม่ในกอง ความสูงของแต่ละแถบจะสอดคล้องกับขนาดของออบเจ็กต์ที่จัดสรรล่าสุด และสีของแถบจะระบุว่าออบเจ็กต์เหล่านั้นยังคงอยู่ในสแนปชอตกองขยะสุดท้ายหรือไม่ โดยแถบสีน้ำเงินจะระบุออบเจ็กต์ที่ยังคงอยู่เมื่อสิ้นสุดไทม์ไลน์ ส่วนแถบสีเทาจะระบุออบเจ็กต์ที่จัดสรรระหว่างไทม์ไลน์ แต่มีการรวบรวมขยะไปแล้ว
ในตัวอย่างข้างต้น มีการดําเนินการ 10 ครั้ง โปรแกรมตัวอย่างแคชออบเจ็กต์ 5 รายการ คุณจึงควรเห็นแถบสีน้ำเงิน 5 แถบสุดท้าย แต่แถบสีน้ำเงินด้านซ้ายสุดบ่งบอกถึงปัญหาที่อาจเกิดขึ้น จากนั้น คุณสามารถใช้แถบเลื่อนในไทม์ไลน์ด้านบนเพื่อซูมเข้าที่ภาพดังกล่าวและดูออบเจ็กต์ที่จัดสรรล่าสุด ณ จุดนั้น การคลิกออบเจ็กต์ที่เฉพาะเจาะจงในกองจะแสดงต้นไม้การคงไว้ในส่วนล่างของสแนปชอตกอง การตรวจสอบเส้นทางการคงไว้ของออบเจ็กต์ควรให้ข้อมูลเพียงพอที่จะทําความเข้าใจสาเหตุที่ระบบไม่รวบรวมออบเจ็กต์ และคุณสามารถทําการเปลี่ยนแปลงโค้ดที่จําเป็นเพื่อนําการอ้างอิงที่ไม่จําเป็นออก
การแก้ปัญหาหน่วยความจำของ Gmail
การใช้เครื่องมือและเทคนิคที่กล่าวถึงข้างต้นช่วยให้ทีม Gmail ระบุข้อบกพร่องได้ 2-3 หมวดหมู่ ได้แก่ แคชที่ไม่มีขอบเขต อาร์เรย์ของคอลแบ็กที่เพิ่มขึ้นอย่างไม่สิ้นสุดซึ่งรอให้เหตุการณ์บางอย่างเกิดขึ้นแต่ไม่เคยเกิดขึ้นจริง และ Listeners เหตุการณ์ที่เก็บเป้าหมายไว้โดยไม่ตั้งใจ การแก้ไขปัญหาเหล่านี้ทำให้การใช้หน่วยความจำโดยรวมของ Gmail ลดลงอย่างมาก ผู้ใช้ใน 99% ใช้หน่วยความจําน้อยกว่าเดิม 80% และปริมาณการใช้หน่วยความจําของผู้ใช้ค่ามัธยฐานลดลงเกือบ 50%
เนื่องจาก Gmail ใช้หน่วยความจำน้อยลง เวลาในการตอบสนองของ GC เมื่อหยุดชั่วคราวจึงลดลง ซึ่งทำให้ประสบการณ์โดยรวมของผู้ใช้ดีขึ้น
นอกจากนี้ ทีม Gmail ยังรวบรวมสถิติเกี่ยวกับการใช้หน่วยความจำ ซึ่งทำให้พบการถดถอยของการเก็บขยะใน Chrome กล่าวโดยละเอียดคือ เราพบข้อบกพร่องการแยกส่วน 2 ข้อเมื่อข้อมูลหน่วยความจำของ Gmail เริ่มแสดงช่องว่างระหว่างหน่วยความจำทั้งหมดที่จัดสรรและหน่วยความจำที่ใช้งานอยู่เพิ่มขึ้นอย่างมาก
คำกระตุ้นให้ดำเนินการ (Call-To-Action)
ลองถามตัวคุณเองด้วยคำถามต่อไปนี้
- แอปของฉันใช้หน่วยความจําเท่าใด คุณอาจใช้หน่วยความจํามากเกินไป ซึ่งขัดแย้งกับความเชื่อที่นิยมว่าส่งผลเสียต่อประสิทธิภาพโดยรวมของแอปพลิเคชัน เป็นเรื่องยากที่จะทราบจำนวนที่ถูกต้อง แต่อย่าลืมตรวจสอบว่าการแคชเพิ่มเติมที่หน้าเว็บใช้อยู่ส่งผลต่อประสิทธิภาพที่วัดได้
- หน้าเว็บของฉันไม่มีการรั่วไหลใช่ไหม หากหน้าเว็บมีการรั่วไหลของหน่วยความจํา ปัญหานี้อาจส่งผลต่อประสิทธิภาพของหน้าเว็บและแท็บอื่นๆ ด้วย ใช้เครื่องมือติดตามวัตถุเพื่อจำกัดขอบเขตการรั่วไหล
- หน้าเว็บของฉันทำ GC บ่อยเพียงใด คุณสามารถดูการหยุดชั่วคราวของ GC โดยใช้แผงไทม์ไลน์ในเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ของ Chrome หากหน้าเว็บของคุณทำ GC บ่อย แสดงว่าคุณอาจจัดสรรหน่วยความจํารุ่นเยาว์บ่อยเกินไป
บทสรุป
เราเริ่มต้นจากวิกฤต ครอบคลุมพื้นฐานหลักๆ ของการจัดการหน่วยความจำใน JavaScript และ V8 โดยเฉพาะ คุณได้เรียนรู้วิธีใช้เครื่องมือ รวมถึงฟีเจอร์เครื่องมือติดตามวัตถุใหม่ที่พร้อมใช้งานใน Chrome เวอร์ชันล่าสุด ทีม Gmail ใช้ความรู้นี้ในการแก้ปัญหาการใช้งานหน่วยความจำและปรับปรุงประสิทธิภาพ คุณทำเช่นเดียวกันกับเว็บแอปได้