diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 37375c0e3a..ae2bf82bb8 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -1765,4 +1765,11 @@ class TestRegexp < Test::Unit::TestCase assert_raise(TypeError) {Regexp.linear_time?(nil)} assert_raise(TypeError) {Regexp.linear_time?(Regexp.allocate)} end + + def test_linear_performance + pre = ->(n) {[Regexp.new("a?" * n + "a" * n), "a" * n]} + assert_linear_performance(factor: 29, first: 10, max: 1, pre: pre) do |re, s| + re =~ s + end + end end diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index 872402727a..12bff170b1 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -738,6 +738,29 @@ eom end alias all_assertions_foreach assert_all_assertions_foreach + def assert_linear_performance(factor: 10_000, first: factor, max: 2, pre: ->(n) {n}) + n = first + arg = pre.call(n) + tmax = (0..factor).map do + st = Process.clock_gettime(Process::CLOCK_MONOTONIC) + yield arg + (Process.clock_gettime(Process::CLOCK_MONOTONIC) - st) + end.max + + 1.upto(max) do |i| + i += 1 if first >= factor + n = i * factor + t = tmax * factor + arg = pre.call(n) + message = "[#{i}]: #{n} in #{t}s" + Timeout.timeout(t, nil, message) do + st = Process.clock_gettime(Process::CLOCK_MONOTONIC) + yield arg + assert_operator (Process.clock_gettime(Process::CLOCK_MONOTONIC) - st), :<=, t, message + end + end + end + def diff(exp, act) require 'pp' q = PP.new(+"")