This patch reduces the number of exceptions raised internally in
Coercer::String when dealing with incoercible values. The motivation
for this change is the cost of raising an exception.
Instead of raising an exception in the private #to_numeric method the
COERCION_FAILURE object is returned. This reduces the number of exceptions
from 2 to 1 in case of #to_float and from 3 to 2 in case of #to_integer.
Consider a following benchmark evaluating the influence of this patch.
require 'benchmark'
require 'coercible'
def test_case(coercer)
100_000.times do
begin
coercer[String].to_integer "asdf"
rescue
end
end
end
coercer = Coercible::Coercer.new
raise unless 0.5 == coercer[String].to_float("0.5")
# warm up before measurements
test_case(coercer)
bm = Benchmark.measure { test_case(coercer) }
p bm
On JRuby 1.7.10 running on OpenJDK 64-Bit Server VM 1.7.0-u60-b01-20131204
this patch improves the benchmark result by 33%. It's exactly one third
because we got rid of 1 out of 3 exceptions; that's how expensive they are!
If you replace #to_integer with #to_float the improvement is even more
apparent; it's nearly 50%. The reason is removal of 50% of exceptions.
Notice that if we would take further steps in this direction and reduce the
number of exceptions raised in #to_integer to 1 we could bring the total
improvement to 66%.
Interestingly enough, on MRI 2.1.1 this patch brings 10% improvement in
case of #to_integer and nearly 30% in case of #to_float. Raising
exceptions isn't that expensive there as on JVM but it still comes with a
noticeable cost.
I did my best to maintain full compatibility of the public API.
This patch reduces the number of exceptions raised internally in Coercer::String when dealing with incoercible values. The motivation for this change is the cost of raising an exception.
Instead of raising an exception in the private #to_numeric method the COERCION_FAILURE object is returned. This reduces the number of exceptions from 2 to 1 in case of #to_float and from 3 to 2 in case of #to_integer.
Consider a following benchmark evaluating the influence of this patch.
On JRuby 1.7.10 running on OpenJDK 64-Bit Server VM 1.7.0-u60-b01-20131204 this patch improves the benchmark result by 33%. It's exactly one third because we got rid of 1 out of 3 exceptions; that's how expensive they are!
If you replace #to_integer with #to_float the improvement is even more apparent; it's nearly 50%. The reason is removal of 50% of exceptions.
Notice that if we would take further steps in this direction and reduce the number of exceptions raised in #to_integer to 1 we could bring the total improvement to 66%.
Interestingly enough, on MRI 2.1.1 this patch brings 10% improvement in case of #to_integer and nearly 30% in case of #to_float. Raising exceptions isn't that expensive there as on JVM but it still comes with a noticeable cost.
I did my best to maintain full compatibility of the public API.