Skip to content

Instantly share code, notes, and snippets.

@kbrock
Last active April 26, 2018 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kbrock/265e86955539a6fbbca43c935f2b1461 to your computer and use it in GitHub Desktop.
Save kbrock/265e86955539a6fbbca43c935f2b1461 to your computer and use it in GitHub Desktop.
Comparing performance implementation of determining whether a field is an integer (for ancestry

note: in the tests, we are setting a different variable @x than the guard clause @x2. I tested a terciary ?: vs the guard clause return if defined?() and they were about the same for pass and fail case

test int i/s slower text i/s slower
eq2 6,315,053.7 i/s same 6,323,409.7 i/s base
neq2 6,281,137.2 i/s same 3,707,761.0 i/s 1.71x
eq 5,978,924.2 i/s same 4,572,438.8 i/s 1.38x
include 4,368,299.8 i/s 1.45x 4,349,531.4 i/s 1.45x
neq 4,194,756.5 i/s 1.51x 4,170,358.7 i/s 1.52x
include2 3,704,824.1 i/s 1.71x 3,718,609.0 i/s 1.70x

thoughts:

  • int and text represent the 2 use cases (pass the match and fail the match)
  • int is the 95% use case as most rails ids are integer. (my group uses bigint instead. I've used uuid in the past)
  • implementation was include2 (worst)
  • changed to include (thanks @NickLaMuro) - His fix then triggered this gist
  • moving an array to a frozen constant is good
  • just directly comparing to values is better
  • trying to be cute and match to the 95% key may work, but there are probably better options
  • shortening the list of compares is better
  • unsure if I want to convert over to comparing with :integer and :bigint - unsure if there are other cases
  • looking up the type of the primary key may overshadow any optimization we gain here
  • only determining need to cast once probably has biggest benefit
require "benchmark/ips"
class Cl
STRING_KEYS = [:string, :uuid, :text].freeze
def int_include
return @x2 if defined?(@x2)
@x = !STRING_KEYS.include?(int)
end
def int_include2
return @x2 if defined?(@x2)
@x = ![:string, :uuid, :text].include?(int)
end
def int_neq
return @x2 if defined?(@x2)
@x = (int != :string && int != :uuid && int != :text)
end
def int_neq2
return @x2 if defined?(@x2)
@x = (int == :integer) || (int != :string && int != :uuid && int != :text)
end
def int_eq
return @x2 if defined?(@x2)
@x = !(int == :string && int == :uuid && int == :text)
end
def int_eq2
return @x2 if defined?(@x2)
@x = (int == :integer) || (int == :bigint)
end
def text_include
return @x2 if defined?(@x2)
@x = !STRING_KEYS.include?(text)
end
def text_include2
return @x2 if defined?(@x2)
@x = ![:string, :uuid, :text].include?(text)
end
def text_neq
return @x2 if defined?(@x2)
@x = (text != :string && text != :uuid && text != :text)
end
def text_neq2
return @x2 if defined?(@x2)
@x = (text == :integer) || (text != :string && text != :uuid && text != :text)
end
def text_eq
return @x2 if defined?(@x2)
@x = !(text == :string || text == :uuid && text == :text)
end
def text_eq2
return @x2 if defined?(@x2)
@x = (int == :integer) || (int == :bigint)
end
private
def int
:integer
end
def text
:text
end
end
cl = Cl.new
Benchmark.ips(5, 3, false) do |x|
x.report("int include") { cl.int_include }
x.report("int include2") { cl.int_include2 }
x.report("int eq") { cl.int_eq }
x.report("int neq") { cl.int_neq }
x.report("int neq2") { cl.int_eq2 }
x.report("int eq2") { cl.int_eq2 }
x.report("text include") { cl.text_include }
x.report("text include2") { cl.text_include2 }
x.report("text eq") { cl.text_eq }
x.report("text neq") { cl.text_neq }
x.report("text neq2") { cl.text_neq2 }
x.report("text eq2") { cl.text_eq2 }
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment