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

ความรู้เบื้องต้นเกี่ยวกับการเก็บขยะ (ตอนที่ 1)

เมื่อใดก็ตามที่คุณรันโค้ด คุณจะใช้หน่วยความจำ เมื่อคุณเขียนในภาษาเช่น Ruby ดูเหมือนว่าหน่วยความจำที่มีให้คุณนั้นไม่มีที่สิ้นสุด คุณสามารถดำเนินการต่อได้โดยไม่ต้องคิดถึงจำนวนหน่วยความจำคงที่ที่ระบบเรียกใช้โค้ดของคุณมี ในตอน Ruby Magic เราจะอธิบายวิธีการทำงาน!

เกร็ดประวัติศาสตร์

ย้อนกลับไปในสมัยนั้น ภาษาสคริปต์เช่น Ruby ยังไม่มีอยู่จริง ผู้คนเขียนโค้ดในภาษาเช่น C ซึ่งเป็นภาษาโปรแกรมระดับต่ำเท่านั้น สิ่งหนึ่งที่ทำให้ภาษาเหล่านี้อยู่ในระดับต่ำคือคุณต้องทำความสะอาดตัวเอง ตัวอย่างเช่น เมื่อใดก็ตามที่คุณจัดสรรหน่วยความจำเพื่อจัดเก็บ String คุณต้องตัดสินใจด้วยว่าจะทำความสะอาดเมื่อใด

การล้างข้อมูลด้วยตนเอง

สิ่งนี้ดูคล้ายกับรหัส Ruby จำลองต่อไปนี้ มันประกาศตัวแปรและใช้วิธี free – วิธีการนี้ไม่มีอยู่ใน Ruby – เพื่อล้างหน่วยความจำที่เราใช้หลังจากที่เราดำเนินการกับตัวแปรเสร็จแล้ว

1_000_000.times do |i|
  variable = "Variable #{i}"
  puts variable
  free(variable)
end

วิธีการเขียนโปรแกรมที่น่าเบื่อ

คุณอาจรู้อยู่แล้วว่ามีความเสี่ยงที่นี่ ถ้าคุณลืม free ตัวแปร? ในกรณีนั้น เนื้อหาของตัวแปรนั้นจะติดอยู่ในหน่วยความจำจนกว่ากระบวนการจะออก หากคุณทำเช่นนี้บ่อยพอ หน่วยความจำของคุณจะหมดและกระบวนการของคุณล่ม

ตัวอย่างต่อไปแสดงให้เห็นถึงปัญหาทั่วไปอื่น:

1_000_000.times do |i|
  variable = "Variable #{i}"
  free(variable)
  puts variable
end

เราประกาศตัวแปรและ free มัน. แต่แล้วเราก็พยายามใช้มันอีกครั้ง ซึ่งเป็นไปไม่ได้ เพราะมันไม่มีอยู่แล้ว หากเป็น C โปรแกรมของคุณจะขัดข้องด้วย segfault . อ๊ะ!

มนุษย์เป็นเครื่องจักรที่ผิดพลาด

มนุษย์มีชื่อเสียงไม่ดีที่ไม่ทำผิดพลาดแบบนี้ตลอดเวลา จึงต้องมีวิธีการล้างหน่วยความจำโดยอัตโนมัติ วิธีที่นิยมที่สุดในการทำเช่นนี้ – ที่ใช้ใน Ruby– คือ Garbage Collection (GC)

วิธีการทำงานของการรวบรวมขยะ (GC)

ในภาษาที่ใช้ GC คุณสามารถสร้างออบเจ็กต์ได้โดยไม่ต้องล้างข้อมูลด้วยตนเอง เมื่อใดก็ตามที่คุณสร้างวัตถุ วัตถุนั้นจะถูกลงทะเบียนกับ Garbage Collector GC พยายามติดตามการอ้างอิงทั้งหมดที่คุณทำกับวัตถุนี้ เมื่อกำหนดว่าคุณไม่ได้ใช้วัตถุอีกต่อไปแล้ว วัตถุนั้นจะถูกทำเครื่องหมายเพื่อล้างข้อมูล Garbage Collector จะหยุดโปรแกรมของคุณชั่วคราวและล้างวัตถุที่ทำเครื่องหมายไว้ทั้งหมดเป็นระยะ

ดูตัวอย่างบางส่วน

ในวงง่าย ๆ ที่เราใช้ก่อนหน้านี้ งานของ GC นั้นค่อนข้างง่าย ทุกครั้งที่วนซ้ำตัวแปรจะไม่ถูกใช้ที่ใดอีกต่อไป สามารถทำเครื่องหมายตัวแปรเพื่อล้างข้อมูลได้ทันที

1_000_000.times do |i|
  variable = "Variable #{i}"
  puts variable
end

ในตัวอย่างต่อไป เราจะส่งตัวแปรไปยัง puts_later วิธีที่รอ 30 วินาทีแล้ว puts ตัวแปร

def puts_later(variable)
  Thread.new do
    sleep 30
    puts variable
  end
end
 
1_000_000.times do |i|
  variable = "Variable #{i}"
  puts_later variable
end

งานของ Garbage Collector ค่อนข้างซับซ้อนในตัวอย่างที่ค่อนข้างง่ายนี้ ต้องเข้าใจว่าเราอ้างอิงตัวแปรใน puts_later กระบวนการ. เนื่องจากวิธีการเริ่มต้นเธรด Garbage Collector จึงต้องติดตามเธรดและรอให้เสร็จสิ้น จากนั้นจึงจะสามารถทำเครื่องหมายตัวแปรเพื่อล้างข้อมูลได้

เมื่อมันซับซ้อน

โดยไม่ต้องยกตัวอย่างที่ซับซ้อน เชื่อฉันเมื่อฉันพูดว่างานของ Garbage Collector นั้นยากจริงๆ สิ่งนี้ยังอธิบายด้วยว่าเหตุใด GC จึงอาจทำให้เกิดค่าใช้จ่ายและปัญหาในสภาพแวดล้อมการผลิตของคุณ จำเป็นต้องมีความเข้าใจอย่างละเอียดถึงสิ่งที่เกิดขึ้นในโปรแกรมของคุณเพื่อล้างหน่วยความจำอย่างเหมาะสม ซึ่งต้องใช้รอบ CPU ค่อนข้างน้อยจึงจะถูกต้อง แต่เดี๋ยวก่อน มันดีกว่าการทำความสะอาดหลังจากตัวคุณเอง!

ขยะยังมีอีกมาก

นี่เป็นเพียงการแนะนำของเราเกี่ยวกับการรวบรวมขยะ ในบทความต่อๆ ไป เราจะมาดูกันว่าสิ่งนี้ทำงานอย่างไรใน Ruby และคุณจะวัดและปรับแต่ง GC ได้อย่างไรเพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชันของคุณ

อัปเดต: รับชมตอนต่อไปได้ที่นี่