Related: Ruby with YJIT for JIT performance, Taxonomy of Ruby Calls for call optimization, A side gig for RuboCop, the Bookworm code crawler for code analysis
require 'benchmark/ips'Benchmark driven development
- set a measruable goal
- Write code
- Measure & improve
TDD:
- Write failing test
- make tit pass
- redo again
Itstead of write fast code from the beginning, it’s hard to make slow code fast
Performance 101: Focus on the bottlenecks
- If something slow, wee should work on that
- Work on the algorithm / architecture
But there’s don’t always be a bottlenecks
- Not Slow != fast
numbers = (1..100).to_a
numbers.select {it.even?}
numbers.find {it.even?}Benchmark every single change in the PR
- Compare before and after change
- Maybe on everypull request
- Maybe on everycommit
- Everytime you type?
BenchDD — Tools
- Set a measurable perf goal
- Write a code
- vim → bench → vim → bench
- Measure & Improve
Benchmark.ips do |x|Benchmark result
- Sinatra 35000ns/req
- Roda: 912 ns /req
- 100x Sinatra: 350ns/req
- Empty Rack: 215ns/req
class Xinatra::Base
def callFull feature Hono was fsater than Empty Rack
Problem
- Benchmark is NOT FUN
- Berchmarking is not provide enough information
Benchmarking Framework
Workloads should be
- Realistic
- Compact
ex:
- Small (10k/reqs)
- Large (100k/reqs)
The important question: information we know: time periteration
How did performance change why did the performance change
Benchmarking & Profiling
- Explaining performance is excatly what profilerls do
We can differeential flamegraph
- Before and After
- Blue are improved
- red are degraded
Important to write benchmark for every feature
- Trie based routing
- Linear routing
- Choosing The Routing Strategy is Important
Importan Info
- params() is slower than params
class
data struct
WHEN YJIT
It’s important to experiment near the production env calling methods is faster than calling blocks Rack::Session
# Slower
hash = {}
hash[key] ||= []
hash[key]
# Faster
hash. = Hash.new {[]}
hash << somethingTips for benchmarking
- CPU Time is very precious
- Databases aren’t very bottlenecks
- Rails is not that IO Bound
- That 1ms could go far especially when scale
- Instead of gcha
- we can do a statistical hypotetical test
- YJIT
- enabling yjit is important
- keep close to prod
Wont profilling affect benchmarking you will see lower scores the profiles enabled
Benchmarking in CI
- Why not run the benchmarking in ci
- Hyper threading
- unstable base cpu
- CI / Envs is VERY UNSTABLE!!!
- Always run benchmarks when writing code
Lesson Learned: 1.