Common Bottlenecks
Speed up Ruby code.
Common Bottlenecks is a free Ruby Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Recognizing Bottlenecks
Most Ruby slowdowns come from a few recurring patterns. Knowing them lets you fix code quickly.
- Wrong data structure for the job
- Repeated work that could be cached
- N+1 queries and nested loops
This lesson covers the most common offenders.
puts 'Speeding up Ruby starts with knowing the usual suspects'Array#include? vs Set
Checking membership with Array#include? is O(n). A Set (or hash) gives O(1) lookups.
- For repeated membership checks, build a Set once
- Huge speedup on large collections
require 'set'
allowed = Set.new(['a', 'b', 'c'])
puts allowed.include?('b')
puts allowed.include?('z')Nested Loops (O(n squared))
Comparing every pair of elements is quadratic and explodes with size.
- Replace inner loops with a hash lookup
- Turns O(n squared) into 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.inspectThe N+1 Pattern
Fetching related data inside a loop causes N+1 operations.
- 1 query for the list, then 1 per item
- Batch the lookups instead with a single grouped fetch
# 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 totalMemoization
Recomputing the same expensive value wastes time. Memoize it with ||=.
- Cache the result after first computation
- Subsequent calls return instantly
class Report
def total
@total ||= begin
puts 'computing...'
(1..1000).sum
end
end
end
r = Report.new
puts r.total
puts r.totalChoosing the Right Method
Some Enumerable methods are far faster than chains.
sumbeatsinject(:+)any?short circuits, unlikeselect.empty?findstops at the first match
nums = (1..1_000_000)
puts nums.any? { |n| n > 5 }
puts nums.find { |n| n > 5 }Avoiding Repeated Sorting
Sorting inside a loop or repeatedly is costly. Sort once and reuse.
- Sorting is O(n log n)
- Cache the sorted result if the data is stable
data = [5, 2, 8, 1, 9]
sorted = data.sort
puts sorted.first
puts sorted.lastHash Grouping
group_by and tally aggregate in one pass instead of repeated scans.
tallycounts occurrences efficiently- Avoids manual counting loops
words = ['a', 'b', 'a', 'c', 'b', 'a']
puts words.tally.inspectString Building Cost
Joining with join is faster than repeated concatenation for collections.
- Build an array, then
joinonce - Avoids many intermediate strings
parts = (1..5).map { |i| "item#{i}" }
puts parts.join(', ')Regex Compilation
Defining a regex literal inside a hot loop recompiles it implicitly. Hoist it to a constant.
- Compile once, match many times
- Use
match?when you only need a boolean
EMAIL = /\A[^@\s]+@[^@\s]+\z/
inputs = ['a@b.com', 'nope', 'x@y.org']
valid = inputs.select { |s| EMAIL.match?(s) }
puts valid.inspectLazy Loading Work
Do not compute what you may never use. Defer with lazy evaluation or guards.
- Return early when possible
- Compute heavy values only on demand
def describe(items)
return 'empty' if items.empty?
"#{items.size} items, first is #{items.first}"
end
puts describe([])
puts describe([10, 20])Quick Check
Test your bottleneck knowledge.
Recap
You learned to fix common bottlenecks:
- Use Set or hash for fast membership instead of
include? - Eliminate nested loops and N+1 patterns with preloaded hashes
- Memoize expensive computations with
||= - Pick efficient methods (
sum,any?,tally) and hoist regexes - Defer or skip work you may never need
Always measure before and after to confirm the gain.
Frequently asked questions
Is the “Common Bottlenecks” lesson free?
Yes — the full text of “Common Bottlenecks” is free to read here on the web, and the Ruby Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Ruby Academy course, upgrade to CoddyKit PRO.
What will I learn in “Common Bottlenecks”?
Speed up Ruby code. You practise Ruby Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Ruby Academy?
No prior experience is required. Ruby Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Common Bottlenecks” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Ruby Academy lesson?
Yes. Every Ruby Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Measuring Performance
- Profiling Tools
- Memory Optimization
- Common Bottlenecks