$ ruby ruby_fast_case_when_set.rb
Warming up --------------------------------------
Array splat 21.000 i/100ms
Set#include? 425.000 i/100ms
Calculating -------------------------------------
Array splat 226.534 (± 5.3%) i/s - 1.134k in 5.019588s
Set#include? 4.282k (± 0.9%) i/s - 21.675k in 5.062326s
Comparison:
Set#include?: 4282.0 i/s
Array splat: 226.5 i/s - 18.90x slower
Created
August 10, 2017 19:51
-
-
Save ms-ati/331f0df61462966e02784d05798bbbe0 to your computer and use it in GitHub Desktop.
What's the fast way to find a constant set of values in a ruby case statement?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# | |
# What's the fast way to find a constant set of values in a ruby case statement? | |
# | |
require "benchmark/ips" | |
require "set" | |
# Provides a `===` operator for a Set | |
class SetCaseEq | |
def initialize(enum) | |
@set = enum.to_set | |
end | |
def ===(val) | |
@set.include?(val) | |
end | |
end | |
NUM = 1_000 | |
ARR = Array.new(NUM) { rand(1..100) }.freeze | |
SET = SetCaseEq.new(ARR) | |
def slow | |
ARR.map do |n| | |
case n | |
when 1 | |
"a" | |
when 42 | |
"b" | |
when *ARR | |
"c" | |
else | |
nil | |
end | |
end | |
end | |
def fast | |
ARR.map do |n| | |
case n | |
when 1 | |
"a" | |
when 42 | |
"b" | |
when SET | |
"c" | |
else | |
nil | |
end | |
end | |
end | |
raise "doesn't work" if slow != fast | |
Benchmark.ips do |x| | |
x.report("Array splat") { slow } | |
x.report("Set#include?") { fast } | |
x.compare! | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment