Shopify2023-10-18Explainer
To Thread or Not to Thread: An In-Depth Look at Ruby’s Execution Models
Summary
Threaded servers such as Puma and thread-based Sidekiq are popular Ruby deployment choices because threads can increase throughput without a proportional increase in memory. The post compares process and thread models using a memory model that separates static application memory from per-request processing memory, then refines it with Copy on Write (CoW), where forked processes share pages until writes force copies. It explains why RSS can double-count shared pages, recommends PSS and Linux’s /proc/$PID/smaps_rollup for more meaningful measurements, and gives a production example in which about two-thirds of static memory is shared. The conclusion is metric-dependent: preload applications to improve CoW, prefer fewer larger containers when appropriate, consider Unicorn for reliable request timeouts, and start web workloads at two threads unless substantial I/O wait justifies more; job processors may benefit from higher counts.
Context
Ruby applications increasingly use threaded web servers and job processors. The stated motivation is to understand the throughput, memory, latency, request-timeout, and Copy on Write trade-offs involved in choosing processes or threads and selecting a thread count.
Approach / What changed
The post builds a simplified memory model for processes and threads, then adds Copy on Write behavior to explain shared and private memory. It compares RSS with PSS and Linux smaps_rollup measurements, uses production memory figures to estimate sharing, and discusses preloading, container sizing, server selection, and thread-count guidance.
Takeaways
RSS can overstate memory usage for forked servers because shared pages are reported for each process; PSS and /proc/$PID/smaps_rollup provide more useful views of actual ownership and sharing.
Preloading the application before forking improves Copy on Write efficiency by allowing more static memory to remain shared; delayed writes and other runtime changes can reduce that benefit.
For threaded web workloads, the guidance is to start with two threads unless the application spends more than half its time waiting on I/O, while job processors can benefit from higher thread counts because they are generally more I/O intensive.
Source and freshness
- Source
- shopify.engineering
- Published
- Added to Yomu
- Last updated
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.