From 6a3fe1f44f03b7b053dfba7bed9c704c2f8b5e99 Mon Sep 17 00:00:00 2001 From: Nikita Vasilevsky Date: Thu, 14 Aug 2025 13:37:43 -0400 Subject: [PATCH] Add Benchmark.ms method and enhance realtime with unit parameter Rails previously included a monkeypatch that added a `ms` method to the Benchmark module to return timing results in milliseconds instead of seconds. This monkeypatch has been deprecated in Rails and will be removed in future versions. ref: https://github.com/rails/rails/commit/4cdf757e2e5aaf00aa1f6b3bd4dba57269622733 This commit adds native support for millisecond timing measurements by adding a new `Benchmark.ms` method that returns elapsed time in milliseconds. For web applications, measuring performance in milliseconds is much more helpful since the majority of operations happen in less than a second. While it's acceptable to display times >1s as "1.2s", showing "0.125s" instead of "125ms" is significantly less readable and intuitive for developers analyzing performance metrics. ```ruby Benchmark.realtime { sleep 0.1 } #=> 0.10023 Benchmark.ms { sleep 0.1 } #=> 100.23 ``` This change provides a clean migration path for Rails applications currently relying on the deprecated monkeypatch while offering enhanced functionality for all benchmark users. --- lib/benchmark.rb | 15 ++++++++++++++- test/benchmark/test_benchmark.rb | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/benchmark.rb b/lib/benchmark.rb index 0d1b8df..00de7e2 100644 --- a/lib/benchmark.rb +++ b/lib/benchmark.rb @@ -325,7 +325,20 @@ def realtime # :yield: Process.clock_gettime(Process::CLOCK_MONOTONIC) - r0 end - module_function :benchmark, :measure, :realtime, :bm, :bmbm + # + # Returns the elapsed real time used to execute the given block. + # The unit of time is milliseconds. + # + # Benchmark.ms { "a" * 1_000_000_000 } + # #=> 509.8029999935534 + # + def ms # :yield: + r0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) + yield + Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - r0 + end + + module_function :benchmark, :measure, :realtime, :ms, :bm, :bmbm # # A Job is a sequence of labelled blocks to be processed by the diff --git a/test/benchmark/test_benchmark.rb b/test/benchmark/test_benchmark.rb index 2e0c47a..182e0b9 100644 --- a/test/benchmark/test_benchmark.rb +++ b/test/benchmark/test_benchmark.rb @@ -156,6 +156,12 @@ def test_realtime_output assert_operator sleeptime, :<, realtime end + def test_ms_output + sleeptime = 1.0 + ms_time = Benchmark.ms { sleep sleeptime } + assert_operator sleeptime * 1000, :<, ms_time + end + # Test that `to_h` returns a hash with the expected data. def test_tms_to_h tms = Benchmark::Tms.new(1.1, 2.2, 3.3, 4.4, 5.5, 'my label')