New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use method_missing #1
base: master
Are you sure you want to change the base?
Conversation
I could, but that would also come at the cost of speed |
theldoria's method_missing defines the method on the first pass, so only the first hit then the method exists. I think someone did a post years ago using "X" as the module name, but can't find it or recall if it had a different purpose. If I used this I'd probably do something horrible like define a utf char (option + x) method on Object to wrap it.
perhaps not for production.. |
True, but send is still slow. |
send method vs native
=====================
Send result: 8
Native result: 8
Warming up --------------------------------------
Send 89.094k i/100ms
Native 118.006k i/100ms
Calculating -------------------------------------
Send 1.180M (± 7.0%) i/s - 5.880M in 5.004923s
Native 1.614M (±11.3%) i/s - 8.024M in 5.022100s
Comparison:
Native: 1614333.5 i/s
Send: 1180439.5 i/s - 1.37x slower Mark code: def run_benchmark(title, quiet = false, **benchmarks)
puts '', title, '=' * title.size, ''
# Validation
benchmarks.each do |benchmark_name, benchmark_fn|
puts "#{benchmark_name} result: #{benchmark_fn.call()}"
end unless quiet
puts
Benchmark.ips do |bm|
benchmarks.each do |benchmark_name, benchmark_fn|
bm.report(benchmark_name, &benchmark_fn)
end
bm.compare!
end
end
task :send_vs_native do
run_benchmark('send method vs native',
'Send': -> { b = 3; cmd = '+'; proc { |a| a.send(cmd, *b) }[5] },
'Native': -> { b = 3; proc { |a| b + a }[5] }
)
end |
Avoiding the use of the splat operator and ensuring to have the command as a symbol can mitigate the performance penalty from the send command a bit. See commit 0c8ec6e. Benchmark results:
using CMD_SYM = :'+'
CMD = '+'
b = 3
run_benchmark('send method vs native',
'Send Optim': -> { proc { |a| a.send(CMD_SYM, b) }[5] },
'Send Splat': -> { proc { |a| a.send(CMD_SYM, *b) }[5] },
'Send No Sym': -> { proc { |a| a.send(CMD, b) }[5] },
'Send': -> { proc { |a| a.send(CMD, *b) }[5] },
'Native': -> { proc { |a| a + b }[5] }) If performance really is an issue one still could provide specialized functions and fall back to |
or perhaps take a cue from your QO evil branch and define it with an eval. |
It is possible to use method_missing, saving you to define the most operators by hand...