Right. Now try that with a long, and you're replacing every piece of code with something that's, what, 20x more verbose? If not more? And becuase of how bad the JVM is, substantially slower.
Look at JGit.
> int myInt = (myBoolean) ? 1 : 0;
Now try to do that throughout the code. Not to mention which, that's a conditional branch for what should be (and is in bytecode) a no-op. (Well, assuming your bytecode is well-conditioned. But the JVM being the JVM, there's no such thing as a boolean, which means you can have the "boolean" value 2, for instance, which seriously messes all sorts of things up.)
Sure, the JVM is supposed to optimize that out. But you can't rely on it being able to do so. At least not if you're not going to use a mainstream JVM.
Halving the time taken. Why? Because the JVM wasn't smart enough to realize that copying an EnumSet for a readonly foreach loop was unnecessary. Oh, and there's more low-hanging fruit there w.r.t. the amount of work (read: reflection) EnumSet has to do behind the scenes to work around Java's type system. Simple. But no, the Java compiler doesn't optimize it out, and the JVM doesn't either.
And that's with adding an additional unnecessary layer of abstraction (unmodifiableSet) that you wouldn't need if Java had a sane type system.
Copying an EnumSet of a small number of elements would be, in a sane language, quite literally just a register move. Ditto, containsAll a bitwise-not and a bitwise-and. But no, "one of the best" optimizing compilers around cannot even do that.
Trying to write high-performance code in Java generally requires tossing out all the supposed advantages of Java. Write your own object pools, whee! Hardcode your own primitive types, whee! Avoid temporary objects, whee! Avoid using polymorphism, whee! Manually unpack arrays inside objects, whee!
My experience with a lot of 'Javaheads' is that they get a little too emphatic about Java's optimizations, most especially the claim that it can out perform C.
BUT
In this case, to be fair, I took his statement to include Hotspot, which can do some pretty cool stuff provided you meet the requirements for it. ie, be long running, have enough memory and horsepower available on the machine to run hotspot, and have paths through the code that rarely jump around (meaning most executions go through the same path).
If you can meet those requirements, my understanding is that the Java ecosystem does a damned fine job.
The issue is that a lot of javaheads will extrapolate that out to the rest of the language and tech and start making claims about Java being the best overall at X, or as fast as language Y (C or C++, take your pick).
This was something that was supposed to be about the single best case for hotspot: a single code path almost always, inside a single while loop that's doing the same thing over and over, with a couple sanity / bail-out checks that are rarely (if ever) called.
And it still didn't optimize something as trivial as avoiding an unnecessary copy that it was taking ~50% of the time doing.
It's too bad - Java is a fine language in many ways (though it tends to be rather overly verbose for no good reason, but meh. Looking at you getters and setters and lack of operator overloading), but it's saddled with a reliance on the arcane to actually get non-hideous performance out of it. I mean: 13ms per copy of what should be a single integer? (Milliseconds! I'm not joking. 595ms inside 47 calls to EnumSet.copyOf (mainly inside Object.clone))
That's, and I'm saying this quite literally, more than a million times slower than what it should be.
Assuming it needs to be done at all, and you can trivially show that it doesn't.
(That being said, I need to explicitly check that Hotspot does do it's full optimization pass on that chunk of code. I see no reason why it wouldn't, but maybe Hotspot doesn't want to. Though that'd be a WTF in and of itself.)
(On a side note: does Java cache hotspot optimizations? I think it does, in which case there's definitely no excuse. And if it doesn't that's a wtf in and of itself.)
(On another side note: is there a Java bytecode-to-bytecode optimizer that'll do optimizations based on the code you've got in front of you now?)
I honestly don't know too much about Java and its technologies outside of a general understanding of it. I specifically chose to stay out of the Java ecosystem years ago because I disliked the Java community as a whole. They had a real beef with C and C++ being more performant and constantly pushed and railed against both C and C++ to the point of being what I considered completely divorced from reality.
Java as a tech is strong, but Java as a community was full of pretentious assholes who had a complex about performance (in my opinion of course).
I have no doubt your example was most likely due to some technical issue preventing hotspot from doing what it should have. When hotspot can do it's work it's amazing, you just have to enable it, and you're right about doing arcane things to get performance. That's true in any GC'd language though, even .Net has it's boogeymen.
Right. Now try that with a long, and you're replacing every piece of code with something that's, what, 20x more verbose? If not more? And becuase of how bad the JVM is, substantially slower.
Look at JGit.
> int myInt = (myBoolean) ? 1 : 0;
Now try to do that throughout the code. Not to mention which, that's a conditional branch for what should be (and is in bytecode) a no-op. (Well, assuming your bytecode is well-conditioned. But the JVM being the JVM, there's no such thing as a boolean, which means you can have the "boolean" value 2, for instance, which seriously messes all sorts of things up.)
Sure, the JVM is supposed to optimize that out. But you can't rely on it being able to do so. At least not if you're not going to use a mainstream JVM.
And no, the JVM is not "one of the best" optimizing compilers around. It's not even a good optimizing compiler. Nowhere near. For a quick counterexample, this: https://github.com/RS485/LogisticsPipes/commit/bb8a57665c4f8...
Halving the time taken. Why? Because the JVM wasn't smart enough to realize that copying an EnumSet for a readonly foreach loop was unnecessary. Oh, and there's more low-hanging fruit there w.r.t. the amount of work (read: reflection) EnumSet has to do behind the scenes to work around Java's type system. Simple. But no, the Java compiler doesn't optimize it out, and the JVM doesn't either.
And that's with adding an additional unnecessary layer of abstraction (unmodifiableSet) that you wouldn't need if Java had a sane type system.
Copying an EnumSet of a small number of elements would be, in a sane language, quite literally just a register move. Ditto, containsAll a bitwise-not and a bitwise-and. But no, "one of the best" optimizing compilers around cannot even do that.
Trying to write high-performance code in Java generally requires tossing out all the supposed advantages of Java. Write your own object pools, whee! Hardcode your own primitive types, whee! Avoid temporary objects, whee! Avoid using polymorphism, whee! Manually unpack arrays inside objects, whee!