0Pricing
Ruby Academy · บทเรียน

การปรับหน่วยความจำให้เหมาะสม

ลดการจัดสรรหน่วยความจำ

การปรับหน่วยความจำให้เหมาะสม เป็นบทเรียน Ruby Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Ruby Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Ruby Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดหน่วยความจำจึงสำคัญ

ออบเจ็กต์ทุกตัวที่ Ruby สร้างขึ้นใช้หน่วยความจำและเพิ่มงานการเก็บขยะ การจัดสรรที่น้อยลงหมายถึงโปรแกรมที่เร็วขึ้นและใช้ทรัพยากรน้อยลง

  • GC จะหยุดทำงานเพื่อเรียกคืนออบเจ็กต์
  • อัตราการจัดสรรสูงจะทำให้ GC ทำงานบ่อยขึ้น
  • การลดการจัดสรรมักให้ผลลัพธ์ที่คุ้มค่าที่สุด
before = GC.stat(:total_allocated_objects)
100.times { 'new string' + '!' }
after = GC.stat(:total_allocated_objects)
puts "Allocated: #{after - before} objects"

การนับการจัดสรร

GC.stat จะแสดงตัวนับการจัดสรร ซึ่งคุณสามารถนำมาเปรียบเทียบก่อนและหลังบล็อกได้

  • :total_allocated_objects จะเพิ่มขึ้นตลอดเวลา
  • นำค่าก่อนและหลังมาหาผลต่างเพื่อวัดส่วนหนึ่งของโปรแกรม
def allocations
  before = GC.stat(:total_allocated_objects)
  yield
  GC.stat(:total_allocated_objects) - before
end

puts allocations { Array.new(1000) { |i| i.to_s } }

สตริงลิเทอรัลแบบไม่เปลี่ยนแปลง

ลิเทอรัลสตริงที่เขียนซ้ำแต่ละครั้งจะจัดสรรออบเจ็กต์ใหม่ การทำให้ไม่เปลี่ยนแปลงช่วยให้ Ruby นำอินสแตนซ์เดียวที่แก้ไขไม่ได้กลับมาใช้ซ้ำได้

  • เพิ่มคอมเมนต์พิเศษไว้ที่ด้านบนสุดของไฟล์
  • หรือเรียกใช้ .freeze กับลิเทอรัลแต่ละตัว
# frozen_string_literal: true

s1 = 'hello'
s2 = 'hello'
puts s1.equal?(s2)

หลีกเลี่ยงการจัดสรรหน่วยความจำในลูป

การสร้างออบเจ็กต์ภายในลูปที่ทำงานถี่จะทำให้การจัดสรรหน่วยความจำเพิ่มขึ้นหลายเท่า ย้ายค่าคงที่ออกไปไว้นอกลูป

  • สร้างนิพจน์ทั่วไป อาร์เรย์ และสตริงเพียงครั้งเดียว
  • นำสิ่งเหล่านั้นกลับมาใช้ซ้ำในแต่ละรอบการทำงาน
PATTERN = /\d+/

def count_numbers(lines)
  lines.count { |line| line.match?(PATTERN) }
end

puts count_numbers(['a1', 'bb', 'c3'])

เมธอดที่เปลี่ยนแปลงข้อมูลเดิม (เครื่องหมาย !)

เมธอดที่ไม่มีเครื่องหมาย ! จะคืนออบเจ็กต์ใหม่ ส่วนเมธอดที่มีเครื่องหมาย !จะแก้ไขข้อมูลเดิมโดยตรง จึงช่วยลดการจัดสรรหน่วยความจำ

  • map!, gsub!, sort!
  • ใช้เฉพาะเมื่อการแก้ไขข้อมูลเดิมนั้นปลอดภัย
arr = [3, 1, 2]
arr.sort!
puts arr.inspect

s = 'hello world'
s.upcase!
puts s

สัญลักษณ์เทียบกับสตริงสำหรับใช้เป็นคีย์

สัญลักษณ์จะถูกเก็บไว้ในตารางภายใน ออบเจ็กต์สัญลักษณ์เดียวกันจึงเป็นออบเจ็กต์ร่วมเพียงตัวเดียว ใช้สัญลักษณ์เป็นคีย์ของแฮช

  • คีย์สตริงจะจัดสรรสตริงใหม่ทุกครั้ง
  • สัญลักษณ์ช่วยประหยัดหน่วยความจำเมื่อค้นหาข้อมูลซ้ำ ๆ
puts :name.equal?(:name)
puts 'name'.equal?('name')

ตัวแจงนับแบบประเมินเมื่อจำเป็น

การเชื่อม map และ select ต่อกันจะสร้างอาร์เรย์ชั่วคราว ส่วน lazy จะประมวลผลสมาชิกทีละตัว

  • ไม่ต้องจัดสรรคอลเลกชันชั่วคราว
  • เหมาะอย่างยิ่งกับลำดับข้อมูลขนาดใหญ่หรือไม่มีที่สิ้นสุด
result = (1..Float::INFINITY).lazy
  .select { |n| n.even? }
  .map { |n| n * n }
  .first(5)
puts result.inspect

อ่านข้อมูลต่อเนื่องแทนการโหลดทั้งหมด

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

  • each_line ประมวลผลทีละบรรทัด
  • ใช้หน่วยความจำคงที่ไม่ว่าขนาดไฟล์จะเท่าใด
text = "line1\nline2\nline3"
text.each_line do |line|
  puts line.strip.upcase
end

การต่อสตริง

การสร้างสตริงด้วย + ภายในลูปจะจัดสรรสตริงใหม่ทุกครั้ง ใช้ << เพื่อเติมข้อมูลลงในสตริงเดิมโดยตรง

  • + สร้างออบเจ็กต์ใหม่
  • << เปลี่ยนแปลงพื้นที่เก็บข้อมูลเดิม
buffer = String.new
5.times { |i| buffer << "item#{i} " }
puts buffer

การจัดการออบเจ็กต์และการใช้ซ้ำ

นำออบเจ็กต์ที่ใช้ทรัพยากรสูงกลับมาใช้ซ้ำ แทนการสร้างใหม่ทุกครั้ง

  • แคช config ที่แยกวิเคราะห์แล้วหรือนิพจน์ทั่วไปที่คอมไพล์แล้ว
  • ใช้ค่าคงที่หรือค่าที่จดจำผลลัพธ์ไว้
def config
  @config ||= { host: 'localhost', port: 4567 }
end

puts config.equal?(config)

เรียกใช้ GC เพื่อดูข้อมูลเชิงลึก

คุณสามารถตรวจสอบการทำงานของ GC เพื่อยืนยันว่าการปรับปรุงมีผล

  • GC.stat(:count) แสดงจำนวนครั้งที่ GC ทำงาน
  • หากจำนวนครั้งลดลงหลังการปรับปรุง ก็ถือเป็นสัญญาณที่ดี
start = GC.stat(:count)
50_000.times { |i| [i] }
puts "GC runs: #{GC.stat(:count) - start}"

ตรวจสอบความเข้าใจ

ทดสอบความรู้เกี่ยวกับการปรับปรุงการใช้หน่วยความจำของคุณ

สรุปทบทวน

คุณได้เรียนรู้วิธีปรับปรุงการใช้หน่วยความจำแล้ว:

  • นับการจัดสรรหน่วยความจำด้วย GC.stat
  • ทำให้ลิเทอรัลสตริงไม่เปลี่ยนแปลงและนำออบเจ็กต์กลับมาใช้ซ้ำ
  • เลือกใช้เมธอดที่มีเครื่องหมาย ! และ << เพื่อหลีกเลี่ยงการสร้างออบเจ็กต์ใหม่
  • ใช้สัญลักษณ์เป็นคีย์ และใช้ตัวแจงนับแบบประเมินเมื่อจำเป็นสำหรับกระบวนการประมวลผลต่อเนื่อง
  • อ่านข้อมูลขนาดใหญ่แบบต่อเนื่องแทนการโหลดทั้งหมด

บทถัดไปคุณจะได้จัดการกับคอขวดด้านประสิทธิภาพที่พบบ่อย

คำถามที่พบบ่อย

บทเรียน “การปรับหน่วยความจำให้เหมาะสม” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การปรับหน่วยความจำให้เหมาะสม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Ruby Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Ruby Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การปรับหน่วยความจำให้เหมาะสม”

ลดการจัดสรรหน่วยความจำ คุณปฏิบัติ Ruby Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Ruby Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Ruby Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การปรับหน่วยความจำให้เหมาะสม” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Ruby Academy นี้ได้ไหม

ได้ บทเรียน Ruby Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การวัดประสิทธิภาพ
  2. เครื่องมือวิเคราะห์ประสิทธิภาพ
  3. การปรับหน่วยความจำให้เหมาะสม
  4. คอขวดที่พบบ่อย
← กลับไปที่ Ruby Academy