Java's GC is actually very optimized in terms of creating lots of objects rapidly in a "burst" fashion. From what I can understand they use a sequential allocator (fastest and simplest O(1) allocator for variable-sized requests) for that kind of "burst cycle" into a memory space they call "Eden space", and only if the objects persist after a GC cycle do they get moved to a place where the GC can collect them one-by-one.
With that said, if your performance needs become critical enough (as in measured with real user-end requirements), then objects do carry an overhead but I wouldn't think of it so much in terms of creation/allocation. It has more to do with locality of reference and the additional size of all objects in Java as required to support concepts like reflection and dynamic dispatch (Float
is bigger than float
, often something like 4 times larger on 64-bit with its alignment requirements, and an array of Float
is not necessarily guaranteed to be stored contiguous from what I understand).
One of the most eye-catching things I ever saw developed in Java that made me consider it a heavyweight contender in my field (VFX) was an interactive, multithreaded standard path tracer (not using irradiance caching or BDPT or MLS or anything else) on the CPU providing real-time previews that converged rather quickly to a noise-free image. I've worked with professionals in C++ dedicating their careers to such things with fancy profilers in hand who had difficulty doing that.
But I peered around at the source code and while it used plenty of objects at trivial cost, the most critical parts of the path tracer (the BVH and triangles and materials) very clearly and deliberately avoided objects in favor of big arrays of primitive types (mostly float[]
and int[]
), which made it use far less memory and guaranteed spatial locality to get from one float
in the array to the next. I don't think it's too speculative to think that, if the author used boxed types liked Float
there, it would have come at a rather large cost to its performance. But we're talking the most absolutely critical part of that engine, and I'm pretty sure, given how skillfully the developer optimized it, that he measured that and applied that optimization very, very judiciously, since he happily used objects everywhere else with trivial cost to his impressive realtime path tracer.
I was told by a colleague that in Java object creation is the most expensive operation you could perform. So I can only conclude to create as few objects as possible.
Even in a field as performance-critical as mine, you're not going to write efficient products if you hamstring yourself in places that don't matter. I would even make the claim that the most performance-critical fields might put an even higher demand for productivity, since we need all the extra time we can get to tune those hotspots that really matter by not wasting such time on things that don't. As with the path tracer example from above, the author skillfully and judiciously applied such optimizations only to the places that truly, truly mattered, and probably in hindsight after measuring, and still happily used objects everywhere else.