Author Build Commit PR
John Hawthorn 25480 3ba9e53 n/a
Repo Branch
rails/rails main
Message
Speed up pluralize and singularize by testing rules with match? apply_inflections tried each rule with sub! until one matched. For a typical word almost every rule fails ("comment" only matches the last of the 33 English plural rules), and a failed sub! is more expensive than a failed match?. Test each rule with match? (or include? for String rules, which sub! matches literally) and only call sub! on the rule that applies. $ ruby /work/ips/exe/ips --markdown --runs 3 --yjit --sha rails/main /work/bench/inflector_bench.rb | Benchmark | Commit | i/s | ± | vs rails/main (7a78da5a55) | | :---------------------------------- | :---------------------- | -------: | ---: | :------------------------- | | `Inflector.pluralize('comment')` | rails/main (7a78da5a55) | 322.818k | 4.3% | baseline | | | faster-pluralize | 652.395k | 2.4% | **2.02 ± 0.10× faster** | | `Inflector.singularize('comments')` | rails/main (7a78da5a55) | 261.245k | 3.2% | baseline | | | faster-pluralize | 501.091k | 2.6% | **1.92 ± 0.08× faster** | | `'comment'.pluralize` | rails/main (7a78da5a55) | 319.214k | 3.5% | baseline | | | faster-pluralize | 651.614k | 2.6% | **2.04 ± 0.09× faster** | | `view.pluralize(2, 'comment')` | rails/main (7a78da5a55) | 292.516k | 4.0% | baseline | | | faster-pluralize | 535.690k | 1.7% | **1.83 ± 0.08× faster** |
Benchmark code `/work/bench/inflector_bench.rb` ```ruby require "bundler/setup" require "active_support" require "active_support/core_ext/string/inflections" require "action_view" require "ips" view = ActionView::Base.empty IPS.run do |x| x.report("Inflector.pluralize('comment')") { ActiveSupport::Inflector.pluralize("comment") } x.report("Inflector.singularize('comments')") { ActiveSupport::Inflector.singularize("comments") } x.report("'comment'.pluralize") { "comment".pluralize } x.report("view.pluralize(2, 'comment')") { view.pluralize(2, "comment") } end ```
Environment ```console $ ips --markdown --runs 3 --yjit --sha rails/main /work/bench/inflector_bench.rb ``` - `ruby 4.0.9 (2026-10-23 revision 3e93b23afc) +YJIT +PRISM [x86_64-linux]` - 3 runs, each reported value is the mean across runs - ips 0.5.0
$ chruby ruby-head $ ruby /work/ips/exe/ips --markdown --runs 3 --yjit --sha rails/main /work/bench/inflector_bench.rb | Benchmark | Commit | i/s | ± | vs rails/main (7a78da5a55) | | :---------------------------------- | :---------------------- | -------: | ----: | :------------------------- | | `Inflector.pluralize('comment')` | rails/main (7a78da5a55) | 554.713k | 1.6% | baseline | | | faster-pluralize | 692.430k | 0.7% | **1.25 ± 0.02× faster** | | `Inflector.singularize('comments')` | rails/main (7a78da5a55) | 434.436k | 0.7% | baseline | | | faster-pluralize | 524.456k | 0.4% | **1.21 ± 0.01× faster** | | `'comment'.pluralize` | rails/main (7a78da5a55) | 542.292k | 2.9% | baseline | | | faster-pluralize | 686.153k | 0.1% | **1.27 ± 0.04× faster** | | `view.pluralize(2, 'comment')` | rails/main (7a78da5a55) | 440.828k | 12.6% | baseline | | | faster-pluralize | 575.887k | 0.5% | **1.31 ± 0.16× faster** |
Benchmark code `/work/bench/inflector_bench.rb` ```ruby require "bundler/setup" require "active_support" require "active_support/core_ext/string/inflections" require "action_view" require "ips" view = ActionView::Base.empty IPS.run do |x| x.report("Inflector.pluralize('comment')") { ActiveSupport::Inflector.pluralize("comment") } x.report("Inflector.singularize('comments')") { ActiveSupport::Inflector.singularize("comments") } x.report("'comment'.pluralize") { "comment".pluralize } x.report("view.pluralize(2, 'comment')") { view.pluralize(2, "comment") } end ```
Environment ```console $ ips --markdown --runs 3 --yjit --sha rails/main /work/bench/inflector_bench.rb ``` - `ruby 4.1.0dev (2026-10-31) +YJIT +PRISM [x86_64-linux]` - 3 runs, each reported value is the mean across runs - ips 0.5.0

/api

Reference documentation

/guides

In-depth tutorials