class RSpec::Benchmark::ComparisonMatcher::Matcher
Implements the `perform_faster_than` and `perform_slower_than` matchers
@api private
Public Class Methods
# File lib/rspec/benchmark/comparison_matcher.rb, line 12 def initialize(expected, comparison_type, **options) check_comparison(comparison_type) @expected = expected @comparison_type = comparison_type @count = 1 @count_type = :at_least @time = options.fetch(:time) { 0.2 } @warmup = options.fetch(:warmup) { 0.1 } @bench = ::Benchmark::Perf::Iteration end
Public Instance Methods
Specify the minimum number of times a block is faster/slower than other. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 83 def at_least(n) set_expected_times_count(:at_least, n) self end
Specify the maximum number of times a block is faster/slower than another. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 91 def at_most(n) set_expected_times_count(:at_most, n) self end
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 141 def description if @count == 1 "perform #{@comparison_type} than comparison block" else "perform #{@comparison_type} than comparison block " \ "by #{@count_type} #{@count} times" end end
Specify exact number of times a block is faster/slower than another. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 99 def exactly(n) set_expected_times_count(:exactly, n) self end
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 131 def failure_message "expected given block to #{description}, but #{failure_reason}" end
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 136 def failure_message_when_negated "expected given block not to #{description}, but #{failure_reason}" end
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 151 def failure_reason return "was not a block" unless @actual.is_a?(Proc) if @ratio < 1 "performed slower by #{format("%.2f", (@ratio**-1))} times" elsif @ratio > 1 "performed faster by #{format("%.2f", @ratio)} times" else "performed by the same time" end end
# File lib/rspec/benchmark/comparison_matcher.rb, line 32 def matcher_name "perform_#{@comparison_type}_than" end
@return [Boolean]
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 39 def matches?(block) @actual = block return false unless @actual.is_a?(Proc) @expected_ips, @expected_stdev, = @bench.run(time: @time, warmup: @warmup, &@expected) @actual_ips, @actual_stdev, = @bench.run(time: @time, warmup: @warmup, &@actual) @ratio = @actual_ips / @expected_ips.to_f case @count_type when :at_most at_most_comparison when :exactly exact_comparison else default_comparison end end
Specify that the code runs faster/slower exactly once. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 106 def once exactly(1) self end
Indicates this matcher matches against a block
@return [True]
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 28 def supports_block_expectations? true end
Specify that the code runs faster/slower exactly thrice. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 119 def thrice exactly(3) self end
No-op, syntactic sugar. @api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 126 def times self end
Specify that the code runs faster/slower exactly twice.
# File lib/rspec/benchmark/comparison_matcher.rb, line 112 def twice exactly(2) self end
The time before measurements are taken
@param [Numeric] value
the time before measurements are taken
@api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 64 def warmup(value) @warmup = value self end
Time to measure iteration for
@param [Numeric] value
the time to take measurements for
@api public
# File lib/rspec/benchmark/comparison_matcher.rb, line 75 def within(value) @time = value self end
Private Instance Methods
At most comparison
@example
@ratio = 3 @count = 4 perform_faster_than { ... }.at_most(@count).times # => true @ratio = 3 @count = 2 perform_faster_than { ... }.at_most(@count).times # => false @ratio = 1/4 @count = 5 perform_slower_than { ... }.at_most(@count).times # => true @ratio = 1/4 @count = 3 perform_slower_than { ... }.at_most(@count).times # => false
@return [Boolean]
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 204 def at_most_comparison if @comparison_type == :faster 1 < @ratio && @ratio < @count else @count**-1 < @ratio && @ratio < 1 end end
# File lib/rspec/benchmark/comparison_matcher.rb, line 265 def check_comparison(type) [:slower, :faster].include?(type) || (raise ArgumentError, "comparison_type must be " \ ":faster or :slower, not `:#{type}`") end
# File lib/rspec/benchmark/comparison_matcher.rb, line 165 def convert_count(n) case n when Numeric then n when :once then 1 when :twice then 2 when :thrice then 3 else raise "The #{matcher_name} matcher is not designed to be used " \ "with #{n} count type." end end
At least comparison, meaning more than expected count
@example
@ratio = 4 @count = 3 perform_faster_than { ... } # => true @ratio = 4 @count = 3 perform_faster_than { ... }.at_least(@count).times # => true @ratio = 1/4 @count = 3 perform_slower_than { ... }.at_least(@count).times # => false @ratio = 1/3 @count = 4 perform_slower_than { ... }.at_least(@count).times # => true
@return [Boolean]
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 257 def default_comparison if @comparison_type == :faster @ratio > @count else @ratio < (1.0 / @count) end end
Check if expected ips is faster/slower than actual ips exactly number of counts.
@example
@ratio = 3.5 @count = 3 perform_faster_than { ... }.exact(@count).times # => true @ratio = 1/4 @count = 4 perform_slower_than { ... }.exact(@count).times # => true
@return [Boolean]
@api private
# File lib/rspec/benchmark/comparison_matcher.rb, line 227 def exact_comparison if @comparison_type == :faster @count == @ratio.round else @count == (1.0 / @ratio).round end end
# File lib/rspec/benchmark/comparison_matcher.rb, line 177 def set_expected_times_count(type, n) @count_type = type @count = convert_count(n) end