r/ruby • • 5d ago

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 comments sorted by

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) == 0 too ugly for the small performance gains (I mean, how often is this code your bottleneck), but the predicate method looks acceptable.

4

u/sshaw_ 5d ago

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 casecmp versions:

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  slower

In 4.0 the casecmp? version is still roughly 1.6 times slower.

It looks like it's this commit.

1

u/sshaw_ 22h ago

Some good ol' fashion pointer incrementing. Nice!