I was just reading about scala's implementation of generics specialization , and it really caught my attention the increase of speed they achieved with this feature. I was wondering what other features have the languages that target the java vm implemented that actually made them perform better than java? I know that the further the generated code moves away from java, the further its performance drops. So I really wonder what other features can a language implement to achieve better performance in java.
Please don't answer this question talking about scala's really nice features on top of java, I'm开发者_JS百科 talking strictly about performance.
Also if you have suggestions that still weren't implemented, please do answer!
Thank you!
Scala does support tail-call optimization, which Java, through the JVM alone, don't fully support yet.
Scala optimizes things like
val nullSafeToString = "" + foo
to
val nullSafeToString = String.valueOf(foo)
Java doesn't, in Java it looks like
val nullSafeToString = new StringBuilder("").append(foo)
which takes 4 times more bytecode than Scala's simpler code and creates a new StringBuilder
instance and an useless String
.
On the one side the JVM was made to support the things they had planned to use in Java, even if the JVM only executes bytecode.
There are features which are missing for ages to better support functional (tailcalls) and untyped languages (InvokeDynamic).
But on the other side I'm surprised how painless the JIT compiler can optimize heavily abstracted code and layers of indirection away and end up with code performing as fast as Java code.
I think that "Pimp My Library" pattern wouldn't be that popular if the JVM couldn't remove the instance creations of these simple implicit
+ class RichFoo
patterns with escape analysis.
Maybe this is too trivial/old/well-known but the Java compiler optimizes String literals and concatenations using a String pool and StringBuilders:
String a = "a";
String b = "a";
String c = a + b + someUserInput;
will actually be closer to
String a = "a";
String b = a;
String a_b = "aa";
String c = new StringBuilder(a_b).append(someUserInput).toString();
or maybe even (not sure)
String a_b = "aa";
String a = a_b.substring(0,1);
String b = a;
String c = new StringBuilder(a_b).append(someUserInput).toString();
Also, the focus of optimization for the Java compiler has shifted from compilation to bytecode (javac) to the compilation from bytecode to machine code (Hotspot). I think there used to be more optimizations in javac, but they have found that to be a bit premature given that Hotspot can do a much more thorough job here (and draw on runtime knowledge about actual hardware and usage patterns).
Another interesting aspect of this is that Hotspot optimizations can improve the performance long after the code was written and compiled. For example, the StringBuilder optimization above used to use the (slightly less efficient) StringBuffer class before Java 5. In order to get the latest improvements, you would need to recompile the code (which is still better than having hand-optimized to use StringBuffer before, in which case you would actually need to update the code).
精彩评论