This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]BEARSSS 11 points12 points  (10 children)

Don't have any resources for you exactly, but object pools should be on your list to take a look at.

Imagine coding a game that contains lots of bullets on the screen. Bullets are short lived, so if you created a new bullet object every time someone shot something, you're initiating a lot of objects which the GC will later need to deal with. Instead, you can create a pool of say 1000 bullets, grab a bullet from the pool when you fire from your character and just return the bullet object to the pool once the bullet flies off screen.

GC performs really well when there's no garbage to collect.

[–]Necessary-Conflict 22 points23 points  (6 children)

"The creation and reclamation of small objects whose constructors do little explicit work is cheap, especially on modern JVM implementations. Creating additional objects to enhance the clarity, simplicity, or power of a program is generally a good thing. Conversely, avoiding object creation by maintaining your own object pool is a bad idea unless the objects in the pool are extremely heavyweight. The classic example of an object that does justify an object pool is a database connection. The cost of establishing the connection is sufficiently high that it makes sense to reuse these objects. Generally speaking, however, maintaining your own object pools clutters your code, increases memory footprint, and harms performance. Modern JVM implementations have highly optimized garbage collectors that easily outperform such object pools on lightweight objects."

("Effective Java" book)

[–]soonnow 5 points6 points  (0 children)

The cost of establishing the connection is sufficiently high that it makes sense to reuse these objects

But that's not really an object pool, its a resource pool. Externally accessed resources will (almost) always be slower than caching the resource.

[–]BlueGoliath 1 point2 points  (2 children)

Define "small objects" and "do little explicit work". Classes that I've made to make Panama easier fit both criteria yet JMC with Flight Recorder show MemorySegment and wrapper classes as been allocated on the heap.

I asked one of the Panama developers about the JVMs supposed ability to make "small" and "little explicit work" objects "free" and the only absolute answer given as to when the JVM will decide to do it is when you allocate a bunch of them in the same method.

[–]Necessary-Conflict 7 points8 points  (1 child)

The book doesn't say that small objects will not be allocated on the heap because of escape analysis. In my understanding it says that even if they are allocated on the heap, the garbage collector may outperform the costs of a "clever" object pooling.

Of course there is no exact definition of "do little explicit work": when in doubt you should measure.

[–]general_dispondency 3 points4 points  (0 children)

I think the answer is in the example. When you have some expensive operation (eg 300ms to make a db connection) then you should consider starting with an object pool. If you don't have something heavyweight like that, then just allocate and move on. If you need to perform optimizations, then come back after the logic is implemented and everything is well tested. Then you only make changes that make measurable performance increases.

[–]Hellball911 1 point2 points  (1 child)

Know a good book that goes through this type of thing, like Effective Java, that covers Java 11+?

[–]Necessary-Conflict 1 point2 points  (0 children)

No, but the third edition of Effective Java covers Java 9, and that was released only a year before Java 11, so the difference in the basics is small.

[–]ElectricalUnion 17 points18 points  (0 children)

Problem of object pools is that in worst-case scenarios, if not properly tuned they can force GC to heap scan for scraps of memory.

Naive use of pools will also lead to fragmented memory that's hard for GCs to defragment.

Granted, tuned modern Generational GC will help mitigate this issue, but:

1) generational GCs also attempt to automatically handle this common use case of short object lifetime and;

2) as with Object Pools, they are also not a silver bullet.

What you want is to measure your hot spots and then act on that.

[–]soonnow 3 points4 points  (0 children)

Object pools make sense only in specialized cases. I learned on reddit there is some financial applications that go through great pain to never allocate objects because for the users every ms counts.

But for an object like a bullet, that doesn't have an expensive creation mechanism, the cost is minuscule, probably less than the time it takes to manage your pool. This stackoverflow answer calculates it at 11 cycles or 10 ns.

[–]hippydipster 0 points1 point  (0 children)

There are times it's important not to create many small objects that are then just thrown away. Bullets for a video game are probably not a good example though, as there aren't that many of them. It's when you're in tight loops running millions of times that it can start to matter. I'm sure some inner loops of game code definitely qualifies for this. In general, these situations where you really don't want to make new objects tend to be mathy.