|
Posted
over 19 years
ago
I wanted to get a feel for Ola's latest commit to see what sort of improvement it will yield. This code dynamically generates bytecode to perform direct invocation to get away from using Java's reflection library's.I used the following script
... [More]
(quick mod from another script since the other script hit a method which used a different dispatch mechanism):require 'benchmark'puts "Test: 100k loops calling arity 100 times"100.times {puts Benchmark.measure { t = Time.now; a = 5; a = a.method(" ") i = 0; while i < 100000 a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; a.arity; i = 1; end puts Time.now - t;}}I then ran this script with reflection enabled and disabled (generated direct invocation):Test: 100k loops accessing a fixnum method and calling arity 100 times -client (java5) | -server (java 5) reflection compileddi mreflected|reflection compileddi mreflected---------------------------------- ----------------------------------- 7.656000 7.546000 24.547000 | 5.484000 5.546000 5.750000 7.375000 7.297000 25.094000 | 6.328000 6.359000 5.938000 7.312000 7.281000 25.031000 | 6.016000 6.047000 5.750000 7.266000 7.297000 24.657000 | 6.125000 6.047000 5.812000Each row represents a completed loop as time goes on you can see the JVM hotspot optimizations that start to take affect. In some cases things end up deoptimizing. Lets compare some more specific numbers.So looking at Java with -client was the first thing I did. If you compare using reflection against the compiled direct invocation code you can see that the direct invocation starts out faster and after hotspot kicks in long enough things kind become a tie. What is significant to me is that the compiled di code starts out faster and does not need hotspot as much. A clear winner for short running code which may not get the benefits of running long enough to be hotspotted.For fun, I wanted to see how this code would work with another dispatching mechanism which I call mreflected. The 'm' in that stands for meta and it is just another way of using Java reflection to invoke methods. I quickly ported the Method code to use mreflected and as you can see from the numbers under client something is horribly wrong. It runs over 3x slower than the other two mechanisms. Weird. We are doing something that hotspot cannot figure out....Or can it.Next thing is running these dispatch mechanisms with -server. You can now see that mreflected clearly wins over the other two. You can also see that hotspot deoptimizes something in the other two.So what is the summary of this? hotspot rocks. The best code is code which behaves best in client AND server and does not rely on hotspot for speed increases. Testing this stuff is very difficult to do....Especially if you consider I only tested Java 5. If I tested Java 1.4 or Java 6 the results will vary. Writing good code is tough and verifying it is good is almost as tough.... [Less]
|