Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

วิธีสร้างหน่วยความจำรั่วใน Ruby

มีบทความสองสามบทความเกี่ยวกับวิธีการค้นหาหน่วยความจำรั่ว

แต่ถ้าสร้างขึ้นมาล่ะ?

ฉันคิดว่ามันจะเป็นแบบฝึกหัดที่น่าสนใจเพื่อให้คุณรู้ว่าหน่วยความจำรั่วใน Ruby เป็นอย่างไร

มาดูตัวอย่างกัน

หลุดง่าย

เราสร้างหน่วยความจำรั่วได้โดยการเพิ่มวัตถุใหม่ลงในอาร์เรย์

ถูกใจสิ่งนี้ :

a = []
b = {}

loop {
  sleep(1)

  10_000.times { a << "abc" }

  puts GC.stat(b)[:heap_live_slots]
}

สิ่งนี้สร้างสตริง 10k ทุกวินาที &จะพิมพ์จำนวนอ็อบเจ็กต์:

285051
295052
305053
315054
325055
335056
345057
355058

จำนวนที่เพิ่มขึ้นเรื่อย ๆ เนื่องจาก GC ไม่สามารถรวบรวมสตริงเหล่านี้ได้ พวกเขากำลังอ้างอิงโดยอาร์เรย์ที่มี (a )

ถ้า a อยู่นอกขอบเขตที่จะอนุญาตให้ GC รวบรวม "abc" . เหล่านี้ทั้งหมด สตริง คุณสามารถทดสอบสิ่งนี้ด้วยตัวอย่างด้านบนโดยการตั้งค่า a ให้เป็นศูนย์ จากนั้นเรียกใช้ GC.start .

คุณสามารถดูตัวอย่างสดได้ที่นี่ เพียงคลิก run เพื่อดูผลลัพธ์

การรั่วไหลของส่วนขยาย C

เมื่อคุณสร้างวัตถุจาก Ruby GC จะติดตามจำนวนหน่วยความจำที่ใช้ แต่เมื่อใช้ส่วนขยาย C Ruby จะไม่สามารถควบคุมสิ่งที่เกิดขึ้นได้

หากคุณสร้างส่วนขยาย C แบบนี้:

#include <ruby.h>
#include "extconf.h"

void *ptr;

void Init_extension()
{
  allocate_memory();
}

void allocate_memory() {
  for(int i = 0; i < 10000; i++) {
   ptr = malloc(1000);
  }
}

allocate_memory() ฟังก์ชันจะทำให้หน่วยความจำรั่วเพราะใช้ malloc และไม่โทรfree เพื่อปลดปล่อยความทรงจำนั้นออกมา

ดังที่คุณเห็นที่นี่:

`ps -o rss -p #{$$}`.lines.last
# "49036"

require './extension'

`ps -o rss -p #{$$}`.lines.last
# "89512"

การรั่วไหลประเภทนี้จะไม่ปรากฏใน heap dump หรือใน GC.stat แต่คุณจะเห็นการใช้หน่วยความจำเพิ่มขึ้น

สรุป

ตอนนี้คุณรู้แล้วว่าหน่วยความจำรั่วเป็นอย่างไร หวังว่าจะช่วยให้คุณค้นหาได้เร็วขึ้นหากคุณเคยประสบปัญหานี้ Btw Ruby 2.4.1 มีหน่วยความจำรั่วที่ทราบ ดังนั้นคุณอาจต้องการอัปเกรดหากคุณใช้เวอร์ชันเฉพาะนี้

คุณมีคำถามข้อเสนอแนะหรือเรื่องราวการดีบักหน่วยความจำรั่วที่น่าสนใจหรือไม่? แสดงความคิดเห็นด้านล่าง 🙂

ขอบคุณสำหรับการอ่าน!