Memory churn is a constant and serious problem
for the performance of your applications.
Allocating loads of temporary objects
in a short period of time puts a ton
of pressure on your memory heaps,
resulting in more GC events being kicked off.
My name is Colt McAnlis.
And rather than promoting a bulk of your objects
to static in order to solve the memory churn problems,
you can utilize an amazingly powerful data structure
known as an object pool.
Typically, memory churn comes from creating a whole group
of temporarily resident objects, like images, or views, paint
objects, and even threads.
They repeatedly get created, exist for a little while,
and then are freed.
This action ends up polluting and fragmenting
the memory heap in a very short amount of time, resulting
in more GC events being kicked off.
When this happens on a regular basis,
you end up getting a hoard of GC events
that occur at a great frequency.
But thankfully, there's a way to get the same functionality
of the allocation and freeing of objects without the GC events,
and it's called an object pool.
Effectively, when you're done with an object,
rather than freeing it back to the memory heap,
you keep a reference to it in a list of available objects.
The next time you need to allocate
an object of that type, you can repurpose an existing object
from the pool rather than grabbing a brand new one
from the memory heap.
Only when your pool is empty does it
make sense to go back to the heap
to allocate new objects, which will eventually
be freed back to the pool, growing
its potential size over time.
The end result of using an object pool
is that instead of a ton of heap fluctuation,
you'll end up with stable allocations or small growths
over time, which, of course, can lead to less GC events being
kicked off, helping you save precious frame time.
But object pools are tricky to get right.
And I have a handful of implementation caveats
that you need to watch out for.
Firstly, remember that there's an overhead involved each time
the object pool needs to go back to the main heap to allocate
memory.
Now it may be small, but it's there,
and you should watch out for it.
As such, rather than allocating an object each time one is
needed, it makes more sense to allocate
a group of free objects at one time
so that the overhead is mitigated
for future allocations.
In addition, rather than waiting for each empty pool request
to make a new heap allocation, instead fill your pool
with objects at application load time
so the first group of objects you're grabbing from the pool
are as fast as possible.
With a little statistics gathering here,
you could even figure out the ideal preallocation amount
so that you can fill your pool ahead of time,
minimizing the number of times you have to go back to the heap
during the lifetime of your application.
However, one of the downsides of objects pools
is that now you, the programmer, are responsible for allocating
and freeing objects manually back to the object pool, which
is a pattern that very much resembles
non-garbage collected languages.
So you might want to limit the usage of object pools
to high churn object sets that demand
this level of interaction.
Otherwise, you'd be wasting a lot
of features of the Java garbage collected language.
And finally, in order to make sure that all of your objects
are returned to the pool properly,
make sure that member variables of these objects
are properly cleaned up so that it doesn't contain
any references to any other objects in memory that
might be valid for the garbage collector to clean up later.
If you're not careful here, you can end up
creating a lot of persistent memory leaks
for these objects in your pools.
There's some intuition involved with finding the right places
for these object pools.
But if you're ever in doubt or looking for new opportunities,
you can use the allocation tracker tool in Android Studio
to identify any areas where you may
be seeing a horde of similar object types coming
from roughly the same call stack in a very short period of time.
This is a classic sign of memory thrashing
and easy to see that it's the right place
to start with object pools.
Anyhow, using object pools are a great way
to reduce memory churn and grab back critical performance
resources.
But like anything else, this feature
comes with a tradeoff in additional code
that makes it happen.
If you're interested in other tradeoffs for performance,
make sure you check out the rest of the Android Performance
Patterns content and join our Google+ page for more tips from
other great developers.
So keep calm, profile your code, and always remember
perf matters.
[MUSIC PLAYING]