COLT MCANLIS: One important part of writing
successful applications is enabling the programmer
to be as efficient as possible so that they
can focus their brain cycles on the truly important problems.
But sometimes this ease of development
can create new performance problems
that aren't always clear.
My name is Colt McAnlis.
And while the Android Runtime provides
lots of opportunities for programmers
to be more efficient, it also presents
a lot of hidden pitfalls with respect to performance.
And the single biggest one that you need to worry about
has everything to do with how you're allocating and using
memory.
See, many programming languages that are known for being "high
performance," like a C and C++, usually require programmers
to manage memory themselves.
That is, the programmer is responsible for allocating
blocks of memory off of the heap during code execution,
and explicitly freeing them back to the heap
once they aren't being used anymore.
But in a 2 million line code base,
it's easy to get lost in logic flows
and end up not freeing allocated memory as intended.
These types of allocations are called leaks-- that is,
memory which was allocated but never freed.
Now, a managed memory environment, on the other hand,
removes this burden of freeing memory from the programmer's
shoulders.
See, it keeps track of each memory allocation.
And once it determines that a piece of memory
is no longer being used by the program,
it can free it back to the heap without any intervention
from the programmer.
Which is great, because we can spend that extra time doing
other things-- like arguing about whether or not
crossguards work on light sabers.
Anyhow, the process of reclaiming
memory in a managed environment is known as Garbage Collection.
It's a concept that was created by John McCarthy back in 1959
to solve problems in the LISP programming language.
And it generally adheres to two primary principles--
find data objects in a program that cannot be accessed
by in the future, and reclaim the resources used by those
objects.
Now, think about it.
Garbage Collection can be really gnarly.
I mean, if you've got some 20,000 allocations
in your program right now, which ones
aren't being needed anymore?
Or better yet, when should you execute a Garbage Collection
event to free up memory that isn't being used?
These are actually very difficult questions.
And thankfully, we've had about 50 years worth of innovation
to improve on them.
Which is why the Garbage Collector in Android Runtime
is quite a bit more sophisticated than McCarthy's
original proposal.
It's been built to be fast and as non-intrusive as possible.
Effectively, the memory heap in Android's Runtime
are segmented into spaces based on the type of allocation
and how best the system can organize those allocations
for future GC events.
As a new object is allocated, the characteristics
are taken into account to best fit
what space it should be placed into,
depending on what version of the Android Runtime you're using.
And here's the important part.
Each space has a set size.
As objects are allocated, we keep
track of the combined sizes.
And as a space starts to grow, the system
will need to execute a Garbage Collection event in an attempt
to free up memory for future allocations.
Now, it's worth pointing out that GC events will
behave differently depending on which Android Runtime
you're using.
For example, in DALVIK, many GC events
are "stop the world" events.
Meaning that any managed code that is running
will stop until the operation completes.
Which can get very problematic when
these GCs take longer than normal,
or there's a ton of them happening at once,
since it's going to significantly eat
into your frame time.
Now, ART, on the other hand, extended
the functionality of a concurrent GC system, which
tends to remove the larger GC pauses, but will still
incur a small pause at the end of important GC events.
And to be clear, our engineers have spent a lot of time
making sure that these events are
as fast as possible to reduce interruptions.
That being said, this can still cause your application
some performance headaches.
Firstly, understand that the more time your app
is spending doing GCs in a given frame,
the less time it's got for the rest of the logic
needed to keep you under the 16 millisecond barrier
for rendering.
So if you've got a lot of GCs, or some long ones
right after each other, it might push your frame processing time
over the 16 millisecond barrier, which
can cause a visible hitching or jink for your users.
Secondly, understand that your code flow
may be doing the kinds of work that
force GCs to occur more often or making them last longer
than normal durations.
For example, if you're allocating
a horde worth of objects in the innermost part of a loop
that runs for a really long time,
then you're going to be polluting your memory
heap with a lot of objects.
And you'll end up kicking off a lot of GC events
quickly due to this additional memory pressure.
And these types of programming patterns are easier to run into
than you'd think.
So thankfully, the Android SDK has
a set of powerful tools at your disposal.
For example, you can get a high-level view
of how your application is managing memory using
the Memory Monitor tool inside of Android Studio.
Every time you see a dip in the allocated memory,
that's a GC event occurring.
Lots of dips in a short time could
signal a performance problem.
And you can see what objects are active in your heap,
and what parts of your code are allocating them,
with the Heap and Allocation Tracker tools as well.
But wrangling memory into performant uses
is easier said than done.
Which is why you need to check out the rest of our Android
Performance Patterns content for other great ways
to improve performance.
And don't forget to join our Google+ community for excellent
info as well.
So keep calm, profile your code, and always remember,
Perf matters.
[MUSIC PLAYING]