Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
performance optimization: Memory
1. Memory
memory leaks
memory churns
Best practices
Don't use a bigger primitive type if you don't
really need it: never use long, float, or double if
you can represent the number with an integer.
Data types
Autoboxing
should be avoided as much as possible
Sparse array family
The number of objects you are dealing with is below a thousand and you are
not going to do a lot of additions and deletions
You are using collections of maps with few items, but lots of iterations
SparseArray
LongSparseArray
SparseIntArray
SparseLongArray
SparseBooleanArray
ArrayMap
Array & Collections
Array
Enhanced for loop syntax is
the fastest way
Enum
static final integer values
Constants
should be static and final
memory savings
avoid initialization in the Java compiler <clinit> method. Object management
Create fewer temporary objects, as they are often garbage collected,
avoid instantiating unnecessary objects, as they are expensive for memory
and computational performance.
StringBuffer
StringBuilder
thread safe
To avoid this unnecessary waste of memory, if you know an estimation
of the string capacity you are dealing with
work on character arrays
String concatenation
Local variables
extract that object from the method
only instantiated once and it's available throughout the life cycle of the class object
Streams
incorrect closeTWR
Memory patterns
The object pool pattern
AsyncTask worker thread
RecyclerView recycled views
limit garbage collection
avoid memory churns
The FlyWeight pattern
expensive creation objects
reduce the load into memory by saving the state shared by all of the objects
Android component leaks
Activities
There is a strong reference between the activity and every
single contained view
static classes
static fields with activity dependencies
singletons
keyword this inside the activity code
strong reference to an object with a longer lifetime.
Context.getApplicationContext()
Non-static inner classes
set the inner class as a static one
provide the reference to that
use a weaker reference to achieve cleaner memory management
Singletons
use a WeakReference inside singleton
Anonymous inner classes
Handlers
Services
handler.postDelayed
anonymous inner classes, let's export that class, setting it as static
handler.removeCallbacksAndMessages(null);
Use IntentService every time you can because of the automatic nalization and because this way you don't risk creating memory leaks with services.
make sure that the Service is finished as soon as it completes its task.
The memory API
Never use the largeHeap attribute inside the Android manifest file to avoid OutOfMemoryError
ComponentCallback2
@Override
public void onTrimMemory(int level) {
switch (level) {
case TRIM_MEMORY_COMPLETE:
//app invisible - mem low - lru bottom
case TRIM_MEMORY_MODERATE:
//app invisible - mem low - lru medium
case TRIM_MEMORY_BACKGROUND:
//app invisible - mem low - lru top
case TRIM_MEMORY_UI_HIDDEN:
//app invisible - lru top
case TRIM_MEMORY_RUNNING_CRITICAL:
//app visible - mem critical - lru top
case TRIM_MEMORY_RUNNING_LOW:
//app visible - mem low - lru top
case TRIM_MEMORY_RUNNING_MODERATE:
//app visible - mem moderate - lru top
break;
}
}
onTrimMemory
LogCat
if the behavior of our application is correct.
Dalvik
D/dalvikvm: <GcReason> <AmountFreed>, <HeapStats>, <ExternalMemoryStats>, <PauseTime>
GC_CONCURRENT: It follows the GC event when the heap needs to be cleared.
GC_FOR_MALLOC: It follows the request of allocation of new memory, but there is not enough space to do it.
GC_HPROF_DUMP_HEAP: It follows a debug request to profile the heap. We will see what this means in the following pages.
GC_EXPLICIT: It follows a forced explicit request of System.gc() that, as we mentioned, should be avoided.
GC_EXTERNAL_ALLOC: It follows a request for external memory. This can happen only on devices lower or equal to Android Gingerbread (API Level 10), because in those devices, memory has different entries, but for later devices the memory is handled in the heap as a whole.
D/dalvikvm(9932): GC_CONCURRENT freed 1394K, 14% free 32193K/37262K, external 18524K/24185K, paused 2ms
ART
I/art: <GcReason> <GcName> <ObjectsFreed>(<SizeFreed>) AllocSpace Objects, <LargeObjectsFreed>(<LargeObjectSizeFreed>) <HeapStats> LOS objects, <PauseTimes>
Concurrent: It follows a concurrent GC event. This kind of event is executed in a different thread from the allocating one, so this one doesn't force the other application threads to stop, including the UI thread.
Alloc: It follows the request for the allocation of new memory, but there is not enough space to do it. This time, all the application threads are blocked until the garbage collection ends.
Explicit: It follows a forced explicit request of System.gc() that should be avoided for ART as well as for Dalvik.
NativeAlloc: It follows the request for memory by native allocations.
CollectorTransition: It follows the garbage collector switch on low memory devices.
HomogenousSpaceCompact: It follows the need of the system to reduce memory usage and to defragment the heap.
DisableMovingGc: It follows the collection block after a call to a particular internal method, called GetPrimitiveArrayCritical.
HeapTrim: It follows the collection block because a heap trim isn't finished.
I/art : Explicit concurrent mark sweep GC freed 125742(6MB) AllocSpace objects, 34(576KB) LOS objects, 22% free, 25MB/32MB, paused 1.621ms total 73.285ms
The ActivityManager API
setWatchHeapLimit
clearWatchHeapLimit
https://developer.android.com/studio/profile/allocation-tracker-walkthru.html
https://developer.android.com/studio/profile/heap-viewer-walkthru.html
Getting a sense of how your app allocates and frees memory.
Identifying memory leaks
call stack
size allocating code
types of objects
how many
sizes
https://developer.android.com/studio/profile/am-memory.html
slowness might be related to excessive garbage collection events
crashes may be related to running out of memory
Memory Monitor
Heap Viewer
Allocation Tracker
compare the heap dumps
creates multiple times but doesn’t destroy
growing memory leak
large arrays
https://developer.android.com/studio/profile/investigate-ram.html
https://developer.android.com/studio/profile/am-allocation.html
object types
Analyzer Tasks
leaked activities
duplicate strings
View
List
for > while > Iterator
private void iteratorCycle(List<String> list) {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String stemp = iterator.next();
}
}
private void whileCycle(List<String> list) {
int j = 0;
while (j < list.size()) {
String stemp = (String) list.get(j);
j++;
}
}
private void forCycle(List<String> list) {
for (int i = 0; i < list.size(); i++) {
String stemp = (String) list.get(i);
}
}
private void classicCycle(Dummy[] dummies) {
int sum = 0;
for (int i = 0; i < dummies.length; ++i) {
sum += dummies[i].dummy;
}
}
private void fasterCycle(Dummy[] dummies) {
int sum = 0;
int len = dummies.length;
for (int i = 0; i < len; ++i) {
sum += dummies[i].dummy;
}
}
private void enhancedCycle(Dummy[] dummies) {
int sum = 0;
for (Dummy a : dummies) {
sum += a.dummy;
}
}
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double
java.lang.Boolean
java.lang.Character
byte: 8 bits
short: 16 bits
int: 32 bits
long: 64 bits
float: 32 bits
double: 64 bits
boolean: 8 bits, but it depends on the virtual machine
char: 16 bits
CPU calculation performance cost memory saving
HashMap
memory wasteCPU operations faster
avoid autoboxing be careful autoboxing
Compaction Resize
define type compile check
use annotation to have a limited number of values
new too many object
Good:
Bad:
Fix:
Basic
Iterate speed
Flow
Key
Runnable