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

Java subclass (instantiation) performance degraded in 9.3 #7763

Open
kares opened this issue Apr 20, 2023 · 2 comments · Fixed by #7762
Open

Java subclass (instantiation) performance degraded in 9.3 #7763

kares opened this issue Apr 20, 2023 · 2 comments · Fixed by #7762

Comments

@kares
Copy link
Member

kares commented Apr 20, 2023

A feature which originated in 9.3 (#6422) seems to have caused a 20x performance degradation in micro-benchmarks compared to 9.2.

This has been observed in production as threads pile up due synchronization and the extra overhead each <init> call has.

The following script demonstrates a Ruby sub-class of a Java class which will have poor class.new performance :

puts RUBY_DESCRIPTION + "\n\n"

require 'benchmark'

class RubyList < java.util.ArrayList

  def initialize(*args) # method's actual logic is irrelevant here
    # the idea is simply that more instructions will slow-down execution more
    foo = args.first.is_a?(NilClass) && args.shift
    bar = args.first.is_a?(String) ? args.shift : self.class.name

    if foo
      super_args = args.dup.to_java(:string)
    elsif bar
      super_args = [bar, *args]
    else
      super_args = args
    end

    super(super_args)
  end

end

time = Benchmark.realtime do
  threads = []
  1000.times do |i|
    threads << Thread.start do
      ('a'..'z').each { |c| 1000.times { RubyList.new(i.to_s, c) } }
    end
  end
  threads.each(&:join)
end

puts "1 RubyList.new(...) elapsed real-time: #{time}"

time = Benchmark.realtime do
  threads = []
  1000.times do |i|
    threads << Thread.start do
      ('a'..'z').each { |c| 1000.times { RubyList.new } }
    end
  end
  threads.each(&:join)
end

puts "2 RubyList.new elapsed real-time: #{time}"
$ jruby slow_java_super.rb 
jruby 9.2.20.0 (2.5.8) 2021-11-02 1a3255440b OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +jit [linux-x86_64]

1 RubyList.new(...) elapsed real-time: 3.4137503600068158
2 RubyList.new elapsed real-time: 2.6153695250031888
$ jruby slow_java_super.rb 
jruby 9.3.10.0 (2.6.8) 2023-02-01 107b2e6697 OpenJDK 64-Bit Server VM 11.0.14.1+1 on 11.0.14.1+1 +jit [x86_64-linux]

1 RubyList.new(...) elapsed real-time: 54.96447179099778
2 RubyList.new elapsed real-time: 54.98580553600186
@kares
Copy link
Member Author

kares commented Aug 14, 2023

for the record: #7762 addressed the main (contention) issue.
but the degradation compared to 9.2 is still there and will require more work to avoid the extra code in Ruby initialize.

@kares
Copy link
Member Author

kares commented Apr 3, 2024

a script that demonstrates single thread perf: https://gist.github.com/kares/f51f8a517d176fd2fdae52471aa7859e
(degradation seems to be ~ 10x)

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 a pull request may close this issue.

1 participant