Sounds right. No need to generate instructions to perform the check if you can rely on a hardware trap, by means of signal-handling cleverness.
> There is no over/underflow checks so I don't know what you mean by arithmetic checks -- in pure number crunching the JVM is insanely fast.
Integer multiplication, addition, and subtraction, are all defined in Java to have wrapping behaviour, and are easily implemented. Whatever the input values, there's no way those operations can fail. (Incidentally, this is a terrible way of handling overflow. This turned up recently in discussion. [0]) Division is trickier. In Java, integer division by zero results in an exception being thrown. Apparently JVMs can implement this with signal-handling cleverness similar to dereferencing null references. [1] Two's complement integer division has another edge case, which is undefined behaviour in C/C++ but which, iirc, results in an exception in Java: INT_MIN / -1. I believe the JIT has to emit instructions to check for this, as it's not possible to leverage signal-handling there.
I don't know how well modern Java performs in floating-point arithmetic. Here's an old tirade about it [2] and discussion. [3]
> with generational GCs it is really cheap.
At the risk of going off topic: doesn't Java tend to perform somewhere around 60% the speed of C/C++, while using considerably more memory? Perhaps the GC isn't to blame, but clearly the blame belongs somewhere. It's like the way advocates of Electron will insist that modern HTML rendering engines are fast and efficient, the DOM is fast and efficient, and JavaScript is fast and efficient... and yet here we are, with Electron-based applications reliably taking several times the computational resources of competing solutions using conventional toolkits.
> primitive classes in Project Valhalla will solve this last problem of object locality
Interesting, sounds like the kind of ambitious initiative that will require deep changes to the JVM.
> At the risk of going off topic: doesn't Java tend to perform somewhere around 60% the speed of C/C++, while using considerably more memory?
It is hard to properly benchmark this generally, for small programs it is “at most” within 2-3X, but I believe for more complex applications it closes the gap quite well (many things can be “dynamically” inlined even between classes far from each other). Not sure how it fares with PGOs.
And yeah it does use more memory, both the runtime/JIT/GC and each object has considerable overhead, but I don’t think that comparing it to Electron is apt. Electron is slow because it adds additional steps to the picture, not because of the JS engine itself. V8 is similarly an engineering gem, and it can be stupidly fast from time to time.
As for the GC:
The GC itself is required for some program to work correctly. C/C++ codebases often create their own GC, and that will surely be slower than any of the multiple GCs found in the JVM. But for short-living programs the GC doesn’t even run (similarly to how some short lived C program leaves clean up to the OS), so rather the former is responsible for the bigger memory usage.
All in all, where ultimate control over memory/execution is not required (that is, you don’t need a low level language), Java is fast enough, especially combined with it being productive and easy (and safe) to refactor, as well as having top notch profiling tools (with so low overhead, that it can be run in production as well).
Sounds right. No need to generate instructions to perform the check if you can rely on a hardware trap, by means of signal-handling cleverness.
> There is no over/underflow checks so I don't know what you mean by arithmetic checks -- in pure number crunching the JVM is insanely fast.
Integer multiplication, addition, and subtraction, are all defined in Java to have wrapping behaviour, and are easily implemented. Whatever the input values, there's no way those operations can fail. (Incidentally, this is a terrible way of handling overflow. This turned up recently in discussion. [0]) Division is trickier. In Java, integer division by zero results in an exception being thrown. Apparently JVMs can implement this with signal-handling cleverness similar to dereferencing null references. [1] Two's complement integer division has another edge case, which is undefined behaviour in C/C++ but which, iirc, results in an exception in Java: INT_MIN / -1. I believe the JIT has to emit instructions to check for this, as it's not possible to leverage signal-handling there.
I don't know how well modern Java performs in floating-point arithmetic. Here's an old tirade about it [2] and discussion. [3]
> with generational GCs it is really cheap.
At the risk of going off topic: doesn't Java tend to perform somewhere around 60% the speed of C/C++, while using considerably more memory? Perhaps the GC isn't to blame, but clearly the blame belongs somewhere. It's like the way advocates of Electron will insist that modern HTML rendering engines are fast and efficient, the DOM is fast and efficient, and JavaScript is fast and efficient... and yet here we are, with Electron-based applications reliably taking several times the computational resources of competing solutions using conventional toolkits.
> primitive classes in Project Valhalla will solve this last problem of object locality
Interesting, sounds like the kind of ambitious initiative that will require deep changes to the JVM.
[0] https://news.ycombinator.com/item?id=26666013
[1] https://www.javaer101.com/en/article/3117893.html
[2] (PDF) https://people.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf
[3] https://news.ycombinator.com/item?id=6585828