[MUSIC PLAYING]
Congratulations.
You've got a great, new social application
that seems to be all the rage.
But you keep getting reports that when users download
a new horde of profile thumbnails,
the application crawls along and feels slow.
My name is Colt McAnlis, and even though you're
in a managed memory environment, improperly using memory
can still kick off a load of performance problems.
And allocating too many objects in a short time frame
is a clear problem that you should be aware of.
You have to remember that the memory heap in Android
is segmented up into separate spaces
based upon what type of allocation is occurring.
And as allocations in any of the spaces grow,
a GC event can be kicked off in order
to make more room for future allocations.
And depending on what runtime you're using,
GC events can be stop-the-world events,
meaning that any managed code that's in flight on any thread
will stop.
The GC event will run, and then only when it's done
will execution continue.
Now, halted execution from a GC event
isn't really normally a noticeable performance problem.
However, a lot of them, occurring over and over
and over and over again, can quickly eat up your frame time.
The more time you're spending doing GCs,
the less time you have to do other interesting stuff,
like rendering or streaming audio.
Now, the number one cause of GC cascades
like this is something called memory churn.
Effectively, memory churn is when a high number of objects
are allocated and potentially freed
in a really small amount of time.
You know, like that new function that you've just
written that checks if a movie director for a new movie
has been swayed by public opinion yet, and, if not,
allocates a horde of social posts
that pushes them up to the inter-tubes.
Yeah.
Just like that.
First off, you should calm down.
This actually isn't really that big of a deal.
Secondly, the quick allocation of so many objects
effectively pollutes the recently allocated
objects space with a flood of reserved memory blocks.
Once you reach a threshold of reserved memory,
a GC event will be kicked off to clear up space.
Even if the memory allocations are tiny, the volume of them
creates pressure on your heap to kick off more GC events
over time, which can eat into your precious frame time
and cause the user to notice a performance
difference since you'll eventually
be slipping past your 16-millisecond rendering
barrier.
Now, fixing these types of problems
are actually pretty straightforward.
To start, if you're noticing, in the Memory Monitor,
that you're getting a flood of GC events
in a very short time frame, then this points to a high chance
that you've got a lot of memory churn going on here.
You can then dig a little deeper using 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 your investigation.
And once you've identified the culprit,
it's time to start moving around your code
to fix the problem, which itself is also pretty straightforward.
For example, make sure that you're not allocating objects
in inner loops for obvious reasons.
Try to push those allocations outside of the loop
or avoid them entirely if you can.
The same advice goes for allocating objects
in the onDraw functions of your views.
This is, effectively, the same problem as an inner loop.
Any time the screen needs to be redrawn
or an animation is occurring, you'll
end up with calls to these functions
every single frame, which can quickly add up,
adding pressure to your heaps.
Now, for situations where you can't remove the need
to create new objects in these scenarios,
consider using an object pool pattern.
Effectively, you have an object pool that
allocates a group of objects.
And rather than having your code go to the heap each time,
it instead grabs available objects from your memory pool.
Of course, the downside to this pattern
is that you're now responsible for freeing objects back
to the memory pool when you're done with them, which
means that for high-churn objects,
there's going to be a bit of a mental overhead needed
to properly manage when these objects are created
and destroyed.
But that's just the tip of the iceberg.
The rest of the Android Performance Patterns content
has other great tips and tricks to solve and address
these problems.
And don't forget to join our Google+ community for other
insights from fellow developers.
So keep calm, profile your code, and always remember,
perf matters.
[MUSIC PLAYING]