Memory Analysis
Overview
Understanding how the Android system works at a low level can help you make better decisions when designing and implementing your application.
We'll review several key concepts from the excellent memory primer from Android's documentation: Managing Your App's Memory.
- There's a constrained heap size for each app. When you run out, you get an
OutOfMemoryError
and Android doesn't defrag your heap.
- If your app holds on to memory it doesn't need it will constrain overall performance, even when cached and in the background.
- You should limit the use of services and properly handle stopping the service when you have one. They aren't usually killed, so they eat a lot of system memory.
- Enums often require more than twice as much memory as static constants.
- Every class in Java (including anonymous inner classes) uses about 500 bytes of code and every class instance has 12-16 bytes of RAM overhead.
- Be careful or abstractions and object-heavy designs as the overhead for managing these objects come at a high cost.
- Limit usage of libraries and dependency injection.
Micro Optimizations
Source: http://developer.android.com/training/articles/perf-tips.html
There are two basic rules for writing efficient code:
- Don't do work that you don't need to do.
- Don't allocate memory if you can avoid it.
- Avoid creating unnecessary objects as "[o]bject creation is never free."
- Use static whenever possible since "[i]nvocations will be about 15%-20% faster."
- Avoid internal getters and setters because it is somewhere between 3x to 7x faster to access the field directly than to invoke a trivial getter.
- Use the enhanced
for
loop as much as possible unless iterating an ArrayList
.
- Use
protected
for inner classes instead of private
.
- Use
int
over float
where possible since it's 2x faster.
Avoiding memory leaks
"[Most] memory leaks [are] due to the same mistake: keeping a long-lived reference to a Context."
- Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
- Try using the context-application instead of a context-activity
- Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
- A garbage collector is not an insurance against memory leaks.
Source: Avoiding Memory Leaks
When we use strong (regular) references, we tell the garbage collector not to collect the memory associated with that variable. That means that we need to keep a close watch on the reference.
Enter WeakReferences. You can tell the garbage collector that you're fine with this reference being cleared up.
WeakReference<Activity> weakActivity;
weakActivity = new WeakReference<Activity>(activity);
Activity activity = weakActivity.get();
if (activity != null) {
// ...
}
Further Exploration