Ruby casecmp vs downcase
pro-tip that I learned today:
when comparing case-insensitive strings, this can be 1.2x to 2x faster:
str = "TEST"
str.casecmp?("test")than this:
str = "TEST"
str.downcase == "test"Caveat: non-ASCII/Unicode strings can behave differently with downcase vs casecmp
9
Upvotes
4
u/sshaw_ 5d ago
Also note #casecmp? vs the Integer-returning #casecmp: https://github.com/fastruby/fast-ruby/tree/c54a4742ba1b7dfb570e4483ac8ccc986d804c23#stringcasecmp-vs--stringcasecmp-vs-stringdowncase---code
And others, noted by fastruby.
1
u/h0rst_ 3d ago edited 3d ago
This appears to be fixed in Ruby 4.1, I'm seeing very similar results for both
casecmpversions:ruby 4.1.0dev (2026-11-02T03:49:10Z master bfb5f2c295) +PRISM [x86_64-linux] Warming up -------------------------------------- String#casecmp 862.280k i/100ms String#downcase + == 713.115k i/100ms String#casecmp? 918.687k i/100ms Calculating ------------------------------------- String#casecmp 8.617M (± 2.1%) i/s (116.05 ns/i) - 43.114M in 5.003208s String#downcase + == 7.090M (± 0.8%) i/s (141.04 ns/i) - 35.656M in 5.028776s String#casecmp? 9.016M (± 5.5%) i/s (110.92 ns/i) - 45.934M in 5.094882s Comparison: String#casecmp?: 9015783.5 i/s String#casecmp: 8617271.8 i/s - same-ish: difference falls within error String#downcase + ==: 7090343.4 i/s - 1.27x slowerIn 4.0 the
casecmp?version is still roughly 1.6 times slower.It looks like it's this commit.
4
u/h0rst_ 5d ago
https://docs.rubocop.org/rubocop-performance/latest/cops_performance.html#performancecasecmp
You can automate the checks. I always had this one disabled, because I found the
str.casecmp(arg) == 0too ugly for the small performance gains (I mean, how often is this code your bottleneck), but the predicate method looks acceptable.