I built high-performance (~1ms) trading/pricing systems in Java and while Java performance is comparable most of the time there are key areas where it's non-competitive, for example garbage collection and socket I/O.
I used various techniques to get around these such as forcing GCs to happen during quiet periods and making kernel modifications to default socket parameters, but it's definitely non-trivial.
So basically, you start with Java, and then you rip out a lot of the features, such as GC, which differentiate it from C++ in order to make it faster. Why not just start with C++?
C++ has failure modes that should horrify anyone who can conceivably use anything else. The slightest mistake is likely to make even correct parts of your program fail in non-deterministic ways. Worst case in a managed runtime like the JVM is an exception and/or a big performance problem, and even those are a lot more likely to happen reproducibly during QA.
I agree that C++, like C before it, has some dangerous failure modes, but Java has them as well. I've been trying literally for years to get some of the people that I work with to understand how dangerous it is to have a runtime exception outright kill one (or many) of the threads in your program if it reaches the top of the stack while leaving the rest of the program limping along as best as it can. The safe default behavior in this case should be the Java equivalent of abort, and I push people to use factories that produce this behavior as much as possible, but I can't count the number of times that I've been trying to make sense of bizarre behavior while testing a program only to suddenly come to my senses and go to the log file where stderr has been redirected and see a ton of stack traces. It's only recently that I've gotten into the habit of checking for that first before I try to make sense of anything else.
With that said, the sort of C++ failure modes that you're talking about tend to mostly occur when working in optimizations, and if you program with a bunch of STL containers and shared pointers (i.e. program C++ like it was Java) then you don't tend to see these problems very much.
Comments
I built high-performance (~1ms) trading/pricing systems in Java and while Java performance is comparable most of the time there are key areas where it's non-competitive, for example garbage collection and socket I/O.
I used various techniques to get around these such as forcing GCs to happen during quiet periods and making kernel modifications to default socket parameters, but it's definitely non-trivial.
So basically, you start with Java, and then you rip out a lot of the features, such as GC, which differentiate it from C++ in order to make it faster. Why not just start with C++?
C++ has failure modes that should horrify anyone who can conceivably use anything else. The slightest mistake is likely to make even correct parts of your program fail in non-deterministic ways. Worst case in a managed runtime like the JVM is an exception and/or a big performance problem, and even those are a lot more likely to happen reproducibly during QA.
I agree that C++, like C before it, has some dangerous failure modes, but Java has them as well. I've been trying literally for years to get some of the people that I work with to understand how dangerous it is to have a runtime exception outright kill one (or many) of the threads in your program if it reaches the top of the stack while leaving the rest of the program limping along as best as it can. The safe default behavior in this case should be the Java equivalent of abort, and I push people to use factories that produce this behavior as much as possible, but I can't count the number of times that I've been trying to make sense of bizarre behavior while testing a program only to suddenly come to my senses and go to the log file where stderr has been redirected and see a ton of stack traces. It's only recently that I've gotten into the habit of checking for that first before I try to make sense of anything else.
With that said, the sort of C++ failure modes that you're talking about tend to mostly occur when working in optimizations, and if you program with a bunch of STL containers and shared pointers (i.e. program C++ like it was Java) then you don't tend to see these problems very much.