การจัดสรรหน่วยความจำทำงานใน Ruby อย่างไร
Ruby ได้รับหน่วยความจำเป็นชิ้น ๆ เรียกว่าเพจ วัตถุใหม่จะถูกบันทึกไว้ที่นี่
แล้ว…
เมื่อหน้าเหล่านี้เต็ม จำเป็นต้องใช้หน่วยความจำเพิ่มขึ้น
Ruby ขอหน่วยความจำเพิ่มเติมจากระบบปฏิบัติการด้วย malloc
ฟังก์ชัน
malloc
นี้ ฟังก์ชั่นเป็นส่วนหนึ่งของระบบปฏิบัติการ แต่มีการใช้งานทางเลือกอื่นที่คุณสามารถใช้ได้
หนึ่งในการใช้งานเหล่านั้นคือ tcmalloc ของ Google
TCmalloc เป็นส่วนหนึ่งของชุดเครื่องมือประสิทธิภาพของ Google
คุณสามารถใช้เครื่องมือเหล่านี้เพื่อสำรวจว่า Ruby จัดสรรหน่วยความจำอย่างไร
และต้องขอบคุณ LD_PRELOAD
ตัวแปรสภาพแวดล้อม (ใน Linux) เราสามารถแทนที่ malloc
. ของระบบของคุณได้ ทำงานด้วย tcmalloc
ถูกใจสิ่งนี้ :
LD_PRELOAD="/usr/lib/libtcmalloc.so" ruby -e "puts 123"
แต่นั่นเป็นเพียงการโหลดไลบรารี่เท่านั้น มันยังไม่ได้เปิดใช้งานการรวบรวมข้อมูลใดๆ
มาดูกันว่าทำอย่างไร
การเปิดใช้งาน Profiler
คุณสามารถเปิดใช้งานตัวสร้างโปรไฟล์ของ tcmalloc ด้วยตัวแปรสภาพแวดล้อมเพิ่มเติม (HEAPPROFILE
)
LD_PRELOAD="/usr/lib/libtcmalloc.so" HEAPPROFILE=/tmp/profile ruby -e "วาง 123"
สิ่งนี้จะสร้างผลลัพธ์ต่อไปนี้:
กำลังเริ่มติดตาม heap123Dumping heap profile ไปยัง /tmp/profile.0001.heap (กำลังออก, ใช้งานอยู่ 2 MB)
ที่นี่คุณจะเห็นการยืนยันว่าได้เปิดใช้งานตัวสร้างโปรไฟล์แล้ว
แล้วเราจะเห็น :
- ผลลัพธ์ของโปรแกรม
- ชื่อไฟล์ (
profile.0001.heap
) - จำนวนหน่วยความจำที่โปรแกรมของเราใช้ (
2 MB
)
หากต้องการอ่านไฟล์นี้ คุณจะต้องมีเครื่องมืออื่นที่มาพร้อมกับ tcmalloc
pprof --text `อันไหน ruby` /tmp/profile.0001.heap | หัว -10
สิ่งนี้จะสร้างผลลัพธ์ต่อไปนี้:
รวม:2.4 MB 1.1 44.7% 44.7% 1.1 44.7% 0x00005570fa4df074 0.7 27.8% 72.5% 0.7 27.8% 0x00005570fa4e0c09 0.4 15.3% 87.8% 0.4 15.3% 0x00005570fa4db460 0.1 5.9% 93.7% 0.1 5.9% 0x00005570fa4df19.9% 0.1 3.2% % 0x00005570fa6349a0 0.0 1.4% 98.3% 0.0 1.4% 0x00005570fa589924 0.0 0.3% 98.6% 0.0 0.3% 0x00005570fa59c4f2 0.0 0.3% 98.8% 0.0 0.3% 0x00005570fa4db48a 0.0 0.2% 99.0% 0.0 0.2% 0x00005570fa4dbaa5 0.0 0.2% 99.1%dl>นั่นเป็นเพียงที่อยู่หน่วยความจำจำนวนมาก! คุณต้องมี Ruby เวอร์ชันที่มีสัญลักษณ์การดีบักจึงจะเห็นชื่อฟังก์ชันได้
แล้วคุณจะได้ผลลัพธ์นี้ :
การใช้ไฟล์ในเครื่อง ruby.Using ไฟล์ในเครื่อง /tmp/profile.0001.heap.Total:2.9 MB 1.0 36.2% 36.2% 1.0 36.2% objspace_xmalloc0 0.7 26.1% 62.4% 0.7 26.1% aligned_malloc 0.5 18.8% 81.1% 0.5 18.8% objspace_xcalloc 0.3 9.9% 91.0% 0.3 9.9% stack_chunk_alloc 0.1 3.7% 94.7% 0.1 3.7% objspace_xrealloc 0.1 2.7% 97.4% 0.1 2.7% Init_Method 0.0 1.3% 98.7% 0.0 1.7% onig_new_with_source 0.0 0.4% 99.2% 0.8 26.6% heap_page_allocate 0.0 0.2% % 0.0 0.2% add_bitsetสิ่งที่คุณเห็นคือจำนวนหน่วยความจำที่ได้รับการจัดสรรโดยการทำงานของ MRI
เป็นเรื่องที่น่าสนใจที่จะรู้ว่า
aligned_malloc
เป็นฟังก์ชันที่ใช้ในการจัดสรรหน้าใหม่สำหรับวัตถุ Rubystack_chunk_alloc
ถูกใช้โดย GC เองในระหว่างขั้นตอนการมาร์ก และobjspace_xmalloc0
/objspace_xcalloc
จัดสรรพื้นที่สำหรับสตริง อาร์เรย์ และข้อมูลอื่นใดที่ไม่พอดีกับRVALUE
โครงสร้างตอนนี้:
TCmalloc ไม่รู้อะไรเลยเกี่ยวกับวัตถุ Ruby สิ่งเดียวที่มันทำคือติดตามการโทรไปยัง malloc, calloc &realloc เพื่อค้นหาจำนวนหน่วยความจำที่ร้องขอ
หากคุณต้องการรับฮีพดัมพ์ที่ระดับ Ruby คุณสามารถใช้
ObjectSpace.dump_all
. สิ่งนี้จะให้ไฟล์ JSON ที่มีอ็อบเจ็กต์สดทั้งหมดในแอปพลิเคชันของคุณและขนาดหน่วยความจำแต่อะไร
tcmalloc
สามารถแสดงให้คุณเห็นเป็นภาพฟังก์ชัน C ทั้งหมดที่สิ้นสุดการขอหน่วยความจำpprof --web `ซึ่ง ruby` /tmp/profile.0001.heapซึ่งจะเป็นการเปิด Chrome หรือ Firefox ด้วยไฟล์ SVG ที่มีลักษณะดังนี้:
TCmalloc ไม่เพียงแต่ให้ความสามารถในการสร้างโปรไฟล์ที่ดีเท่านั้น แต่คุณยังสามารถเพิ่มประสิทธิภาพแอปพลิเคชันของคุณได้ 4-9% ด้วย! คุณสามารถลอง
jemalloc
ซึ่งเป็นอีกmalloc
การนำไปใช้งานที่มีตัวสร้างโปรไฟล์ด้วยสรุป
คุณได้เรียนรู้วิธีใช้ gperftools (Google Performance Tools) เพื่อแสดงภาพและวิเคราะห์การใช้หน่วยความจำของล่าม Ruby
ขอบคุณที่อ่าน! 🙂