การปรับหน่วยความจำให้เหมาะสม
ลดการจัดสรรหน่วยความจำ
การปรับหน่วยความจำให้เหมาะสม เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การวัดประสิทธิภาพ
- เครื่องมือวิเคราะห์ประสิทธิภาพ
- การปรับหน่วยความจำให้เหมาะสม
- คอขวดที่พบบ่อย