Skip to content
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

Improve unsupported coercion performance by optionally caching error #23

Closed
wants to merge 1 commit into from
Closed

Improve unsupported coercion performance by optionally caching error #23

wants to merge 1 commit into from

Conversation

ivoanjo
Copy link

@ivoanjo ivoanjo commented Jul 11, 2017

As identified in #16 and jruby/jruby#4540, coercible's use of errors
to signal unsupported coercions has a measurable impact on performance, especially when using JRuby.

To workaround this problem, this PR adds the option (controlled by the setting the COERCIBLE_CACHE_UNSUPPORTED_COERCION_ERROR environment variable to '1', off by default) to reuse a cached error object, rather than raising a new instance every time.
This saves a big slice of the cost of using errors, but trades it off with having a useless backtrace -- all UnsupportedCoercion errors will share the same backtrace.

It also includes a benchmark that can be used to measure the impact of this change. Here are some results of the benchmark on my local machine (Core i7-6500U, Ubuntu 17.04):

  • ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]:

      cached_unsupported_coercion_error
        559.584k (± 8.3%) i/s -     16.664M in  30.057606s
      noncached_unsupported_coercion_error
        287.123k (±13.9%) i/s -      8.402M in  30.018748s
    
      Comparison:
        cached_unsupported_coercion_error:   559583.7 i/s
        noncached_unsupported_coercion_error:   287123.4 i/s - 1.95x  slower
    
  • jruby 9.1.7.0 (2.3.1) 2017-01-11 68056ae Java HotSpot(TM) 64-Bit Server VM 25.131-b11 on 1.8.0_131-b11 +indy +jit [linux-x86_64]:

      cached_unsupported_coercion_error
        797.391k (± 9.1%) i/s -     23.619M in  29.979835s
      noncached_unsupported_coercion_error
        589.736k (± 9.0%) i/s -     17.477M in  29.996031s
    
      Comparison:
        cached_unsupported_coercion_error:   797390.8 i/s
        noncached_unsupported_coercion_error:   589735.9 i/s - 1.35x  slower
    
  • jruby 9.1.12.0 (2.3.3) 2017-06-15 33c6439 Java HotSpot(TM) 64-Bit Server VM 25.131-b11 on 1.8.0_131-b11 +indy +jit [linux-x86_64]

      cached_unsupported_coercion_error
        843.364k (± 8.4%) i/s -     24.977M in  29.973919s
      noncached_unsupported_coercion_error
        5.757k (±10.5%) i/s -    169.785k in  30.029482s
    
      Comparison:
        cached_unsupported_coercion_error:   843363.9 i/s
        noncached_unsupported_coercion_error:     5757.1 i/s - 146.49x  slower
    

    (The difference here to 9.1.7.0 is due to the "regression" in Performance regression when going from 9.1.7.0 to 9.1.8.0 with virtus gem jruby/jruby#4540)

As identified in <#16> and
<jruby/jruby#4540>, coercible's use of errors
to signal unsupported coercions has a measurable impact on performance,
especially when using JRuby.

To workaround this problem, this PR adds the option (controlled by the
setting the `COERCIBLE_CACHE_UNSUPPORTED_COERCION_ERROR` environment
variable to `'1'`, off by default) to reuse a cached error object,
rather than raising a new instance every time.
This saves a big slice of the cost of using errors, but trades it off
with having a useless backtrace -- all `UnsupportedCoercion` errors will
share the same backtrace.

It also includes a benchmark that can be used to measure the impact of
this change. Here are some results of the benchmark on my local machine
(Core i7-6500U, Ubuntu 17.04):

* `ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]`:

        cached_unsupported_coercion_error
          559.584k (± 8.3%) i/s -     16.664M in  30.057606s
        noncached_unsupported_coercion_error
          287.123k (±13.9%) i/s -      8.402M in  30.018748s

        Comparison:
          cached_unsupported_coercion_error:   559583.7 i/s
          noncached_unsupported_coercion_error:   287123.4 i/s - 1.95x  slower

* `jruby 9.1.7.0 (2.3.1) 2017-01-11 68056ae Java HotSpot(TM) 64-Bit
Server VM 25.131-b11 on 1.8.0_131-b11 +indy +jit [linux-x86_64]`:

        cached_unsupported_coercion_error
          797.391k (± 9.1%) i/s -     23.619M in  29.979835s
        noncached_unsupported_coercion_error
          589.736k (± 9.0%) i/s -     17.477M in  29.996031s

        Comparison:
          cached_unsupported_coercion_error:   797390.8 i/s
          noncached_unsupported_coercion_error:   589735.9 i/s - 1.35x  slower

* `jruby 9.1.12.0 (2.3.3) 2017-06-15 33c6439 Java HotSpot(TM) 64-Bit
Server VM 25.131-b11 on 1.8.0_131-b11 +indy +jit [linux-x86_64]`

        cached_unsupported_coercion_error
          843.364k (± 8.4%) i/s -     24.977M in  29.973919s
        noncached_unsupported_coercion_error
          5.757k (±10.5%) i/s -    169.785k in  30.029482s

        Comparison:
          cached_unsupported_coercion_error:   843363.9 i/s
          noncached_unsupported_coercion_error:     5757.1 i/s - 146.49x  slower

  (The difference here to 9.1.7.0 is due to the "regression" in
   jruby/jruby#4540)
@Talkdesk Talkdesk closed this by deleting the head repository Jan 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants