Meshing software is a typical program where you need C++ and where Java is a terrible choice.
By nature, meshing makes you play with millions to billions of very small object with mutual interactions. A thing that Java GC absolutely hate. Sorry for the Java fan-boys.
Performant mesh manipulation code as a rule deals with largish float arrays (or other similar contiguous layouts, like AoS or SoA or indexed versions thereof). So there are no per-vertex objects to malloc/free or to track in GC.
In some algorithms, other data structures such as trees, may be used used as intermediate formats, but there too the options to use malloc/gc allocated nodes vs alternatives is similar in a GC'd vs a non-GC'd language.
In general, good GC's often outperform malloc/free. Because GC's are amenable to parallelization in the background, and because malloc/free don't enjoy the bump-allocator style happy case that is used in generational GC's nursery objects.
Performance-optimized use of malloc and free involves using custom suballocators (often called simply "allocators" within user code) which are tailored to the "happy cases" that you know about in your code. A "nursery" of objects that can be bump-allocated and then freed in a single operation is known in this context as an arena/region, and you absolutely can exploit this pattern as part of using malloc/free.
Here again, this is wrong.
99% of highly scalable parallel code that run on supercomputers is C++ or Fortran.
And there is reasons to that, if you want parallelism, you want generally performance. If you want performance you want control on NUMA, SIMD, cache locality, etc... and C++ gives you that. Not Java.
Java is not the only language with GC, there are others which offer control over NUMA, SIMD, cache locality, like .NET Native with C# 7/8, or D as two possible examples.
A vocal sub-community of D programmers argue for @nogc due to GC phobia, as ex-C++ devs, and a GC implementation found lacking. A situation that might improve with the recently released GC pluggable API and a new precise tracing GC.
Many devs that prototype their apps in D without doing premature memory optimizations, end up realizing that for their use case it actually good enough.
> Performant mesh manipulation code as a rule deals with largish float arrays (or other similar contiguous layouts, like AoS or SoA or indexed versions thereof). So there are no per-vertex objects to malloc/free or to track in GC.
To store custom vertex / face attributes, you can use a variety of sparse techniques to save memory from sitting unused in attribute arrays. Basically you want an interface of get_attribute(type, vertex_id). This sparse matrix, trie, or whatever can be backed by int or float array storage instead of many many tiny malloc'd/gc'd objets.
I converted that code to C++ and recently added a custom allocator to improve performance even further. The result is now functionally equivalent, but about 5 times faster.
No. That's on synthetic benchmarks. Run a real server and you see that Java shits its pants while a C++ service is running rings around it.
That's because memory/cache fragmentation and usage is vastly more important in 2019 than CPU cycles.
And in this case, the author does need cpp speed.
Because you can be a lot more productive if you are not extremely constrained by speed.
The app is Dust3D, a ease-of-use focused mesh editor which deals with simple meshes.
Certainly from the blog post you get the impression that programmer productivity is a consideration in his choice of language.
The code needs to be "fast enough"¹. Though this often means more attention to speed than in other kinds of software. To rephrase, speed is often necessary but not sufficient to make good tools.
¹ I try to avoid using "execution speed" and "performance" interchangeably, since a crashing, late or incorrect fast program is not a well performing program!