คอขวดที่พบบ่อย
เร่งโค้ด Ruby
คอขวดที่พบบ่อย เป็นบทเรียน Ruby Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Ruby Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Ruby Academy มีบทเรียนทั้งหมด 4 บทเรียน
การระบุคอขวด
การทำงานช้าลงของ Ruby ส่วนใหญ่มาจากรูปแบบที่เกิดซ้ำอยู่ไม่กี่แบบ หากรู้จักรูปแบบเหล่านี้ คุณก็จะแก้ไขโค้ดได้อย่างรวดเร็ว
- เลือกใช้โครงสร้างข้อมูลไม่เหมาะกับงาน
- ทำงานซ้ำทั้งที่สามารถเก็บไว้ในแคชได้
- การสอบถามข้อมูลแบบ N+1 และลูปซ้อนกัน
บทเรียนนี้ครอบคลุมปัญหาที่พบบ่อยที่สุด
puts 'Speeding up Ruby starts with knowing the usual suspects'Array#include? เทียบกับเซต
การตรวจสอบสมาชิกด้วย Array#include? มีความซับซ้อน O(n) ส่วนเซต (หรือแฮช) ให้การค้นหาที่มีความซับซ้อน O(1)
- หากต้องตรวจสอบสมาชิกซ้ำ ๆ ให้สร้างเซตเพียงครั้งเดียว
- ช่วยเพิ่มความเร็วได้มากกับคอลเลกชันขนาดใหญ่
require 'set'
allowed = Set.new(['a', 'b', 'c'])
puts allowed.include?('b')
puts allowed.include?('z')ลูปซ้อนกัน (O(n ยกกำลังสอง))
การเปรียบเทียบสมาชิกทุกคู่มีความซับซ้อนระดับกำลังสอง และจะเพิ่มขึ้นอย่างรวดเร็วเมื่อขนาดข้อมูลใหญ่ขึ้น
- แทนที่ลูปด้านในด้วยการค้นหาในแฮช
- เปลี่ยนความซับซ้อนจาก O(n ยกกำลังสอง) เป็น O(n)
a = [1, 2, 3, 4]
b = [3, 4, 5]
set_b = b.to_set rescue require('set') || b.to_set
common = a.select { |x| set_b.include?(x) }
puts common.inspectรูปแบบ N+1
การดึงข้อมูลที่เกี่ยวข้องภายในลูปทำให้เกิดการดำเนินการ N+1 ครั้ง
- สอบถามข้อมูล 1 ครั้งสำหรับรายการ จากนั้นสอบถามอีก 1 ครั้งต่อสมาชิกแต่ละตัว
- เปลี่ยนเป็นดึงข้อมูลแบบรวมกลุ่มด้วยการสอบถามเพียงครั้งเดียว
# Bad: lookup inside loop
orders = [1, 2, 3]
prices = { 1 => 10, 2 => 20, 3 => 30 }
# Good: one preloaded hash, O(1) per item
total = orders.sum { |id| prices[id] }
puts totalการจดจำผลลัพธ์
การคำนวณค่าที่ใช้ทรัพยากรสูงซ้ำ ๆ เป็นการเสียเวลา ให้จดจำผลลัพธ์ด้วย ||=
- เก็บผลลัพธ์ไว้ในแคชหลังจากคำนวณครั้งแรก
- การเรียกใช้ครั้งต่อ ๆ ไปจะคืนค่าทันที
class Report
def total
@total ||= begin
puts 'computing...'
(1..1000).sum
end
end
end
r = Report.new
puts r.total
puts r.totalการเลือกเมธอดที่เหมาะสม
เมธอดสำหรับประมวลผลสมาชิกบางเมธอดทำงานเร็วกว่าการเชื่อมเมธอดหลายตัวต่อกันมาก
sumเร็วกว่าinject(:+)any?จะหยุดทำงานทันทีเมื่อได้คำตอบ ต่างจากselect.empty?findจะหยุดเมื่อพบสมาชิกที่ตรงกันตัวแรก
nums = (1..1_000_000)
puts nums.any? { |n| n > 5 }
puts nums.find { |n| n > 5 }หลีกเลี่ยงการเรียงลำดับซ้ำ
การเรียงลำดับภายในลูปหรือเรียงซ้ำหลายครั้งใช้ทรัพยากรมาก ให้เรียงลำดับเพียงครั้งเดียวแล้วนำผลลัพธ์กลับมาใช้ซ้ำ
- การเรียงลำดับมีความซับซ้อน O(n log n)
- เก็บผลลัพธ์ที่เรียงแล้วไว้ในแคช หากข้อมูลไม่มีการเปลี่ยนแปลง
data = [5, 2, 8, 1, 9]
sorted = data.sort
puts sorted.first
puts sorted.lastการจัดกลุ่มด้วยแฮช
group_by และ tally รวบรวมข้อมูลได้ในการวนดูเพียงรอบเดียว แทนการตรวจดูซ้ำหลายครั้ง
tallyนับจำนวนครั้งที่ปรากฏได้อย่างมีประสิทธิภาพ- ช่วยหลีกเลี่ยงลูปนับจำนวนที่เขียนขึ้นเอง
words = ['a', 'b', 'a', 'c', 'b', 'a']
puts words.tally.inspectต้นทุนการสร้างสตริง
การรวมด้วย join เร็วกว่าการต่อสตริงซ้ำ ๆ เมื่อทำงานกับคอลเลกชัน
- สร้างอาร์เรย์ก่อน แล้วใช้
joinเพียงครั้งเดียว - ช่วยหลีกเลี่ยงการสร้างสตริงชั่วคราวจำนวนมาก
parts = (1..5).map { |i| "item#{i}" }
puts parts.join(', ')การคอมไพล์นิพจน์ทั่วไป
การกำหนดลิเทอรัลนิพจน์ทั่วไปไว้ในลูปที่ทำงานบ่อยจะทำให้เกิดการคอมไพล์ซ้ำโดยปริยาย ย้ายไปไว้เป็นค่าคงที่
- คอมไพล์ครั้งเดียว แล้วจับคู่ได้หลายครั้ง
- ใช้
match?เมื่อคุณต้องการเพียงค่าจริงหรือเท็จ
EMAIL = /\A[^@\s]+@[^@\s]+\z/
inputs = ['a@b.com', 'nope', 'x@y.org']
valid = inputs.select { |s| EMAIL.match?(s) }
puts valid.inspectเลื่อนการประมวลผลที่ไม่จำเป็น
อย่าคำนวณสิ่งที่คุณอาจไม่ได้ใช้ ให้เลื่อนการทำงานด้วยการประเมินเมื่อจำเป็นหรือใช้เงื่อนไขตรวจสอบ
- คืนค่ากลับทันทีเมื่อทำได้
- คำนวณค่าที่ใช้ทรัพยากรสูงเมื่อต้องการเท่านั้น
def describe(items)
return 'empty' if items.empty?
"#{items.size} items, first is #{items.first}"
end
puts describe([])
puts describe([10, 20])ตรวจสอบความเข้าใจ
ทดสอบความรู้เกี่ยวกับคอขวดของคุณ
สรุปทบทวน
คุณได้เรียนรู้วิธีแก้ไขคอขวดที่พบบ่อยแล้ว:
- ใช้เซตหรือแฮชเพื่อตรวจสอบสมาชิกอย่างรวดเร็ว แทน
include? - กำจัดลูปซ้อนกันและรูปแบบ N+1 ด้วยแฮชที่เตรียมข้อมูลไว้ล่วงหน้า
- จดจำผลลัพธ์ของการคำนวณที่ใช้ทรัพยากรสูงด้วย
||= - เลือกเมธอดที่มีประสิทธิภาพ (
sum,any?,tally) และย้ายนิพจน์ทั่วไปออกจากลูป - เลื่อนหรือตัดการทำงานที่คุณอาจไม่จำเป็นต้องใช้
วัดผลก่อนและหลังเสมอเพื่อยืนยันว่าประสิทธิภาพดีขึ้น
คำถามที่พบบ่อย
บทเรียน “คอขวดที่พบบ่อย” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คอขวดที่พบบ่อย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Ruby Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Ruby Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คอขวดที่พบบ่อย”
เร่งโค้ด Ruby คุณปฏิบัติ Ruby Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Ruby Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Ruby Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “คอขวดที่พบบ่อย” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Ruby Academy นี้ได้ไหม
ได้ บทเรียน Ruby Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ