I am writing a toy game that uses very simple keyboard commands. I need to do a lot of checking to see if certain keys are pressed and I want to ignore case so I do a lot of things like this:
if keycode == 'c' || keycode == 'C'
blah blah
end
That is ugly and a lot of typing if I have more than a few keys I want to check against. So I tried this for brevity:
if keycode in Set(['c', 'C'])
blah blah
end
They both work fine but I was curious about performance so I ran a simple speed check (full code at the bottom)
I found that the â||
â version was 6-7 times faster than the âSet
â version ( I controlled for the ||
case exiting early, see code below)
So, I decided to try to code a macro to write the â||
â version a bit more succinctly. Well that didnât end well, so I decided to make a âmulti_orâ function that took in the test variable and the values to check against and returned a Bool (again, see below). That version was by far the fastest of the three, ~800 times faster than the âSet
â version and ~140 times faster than the â||
â version.
That really confused me. Can anyone hazard a guess at why the function multi_or
is so much faster than the plain â||â code?
Here are test results:
julia> x=rand(100_000_000);
julia> include("speedcheck.jl")
julia> @time set_test(x)
17.177306 seconds (500.00 M allocations: 40.233 GiB, 18.02% gc time)
49999593
julia> @time or_test(x)
2.799505 seconds
49999593
julia> @time multi_or_test(x)
0.020058 seconds
49999593
speedcheck.jl:
"""Call these tests with a random vector of floats to prevent the compiler
from trying to outsmart the test"""
function set_test(vec::Vector{Float64})
c::Char = 'g'
sum::Int64 = 0
for val in vec
if val > 0.5
c = 'C'
else
c = 'K'
end
#put the successful test value at the end to makes things worse
if c in Set(['c', 'a', 'b', 'd', 'e', 'f', 'F', 'C'])
sum += 1
end
end
return sum
end
function or_test(vec::Vector{Float64})
c::Char = 'g'
sum::Int64 = 0
for val in vec
if val > 0.5
c = 'C'
else
c = 'K'
end
#put the successful test value at the end to makes things worse
if c == 'c' || c == 'a' || c == 'b' || c == 'd' || c == 'e' || c == 'f' || c == 'F' || c == 'C'
sum += 1
end
end
return sum
end
function multi_or(val, choices...)::Bool
for choice in choices
if val == choice
return true
end
end
return false
end
function multi_or_test(vec::Vector{Float64})
c::Char = 'g'
sum::Int64 = 0
for val in vec
if val > 0.5
c = 'C'
else
c = 'K'
end
#put the successful test value at the end to makes things worse
if multi_or(c, 'c', 'a', 'b', 'd', 'e', 'f', 'F', 'C')
sum += 1
end
end
return sum
end
'''