Upload
others
View
6
Download
0
Embed Size (px)
Citation preview
Optimizing Your Android Applications
Alexander Nelson
November 22, 2019
University of Arkansas - Department of Computer Science and Computer Engineering
The Problem
Reminder – Immediacy and responsiveness
Three time limits1:
• < 0.1s - User feels system acts instantaneously
• < 1s - Maintain user’s flow of thought
• < 10s - Maintain user’s attention
Plan for these limits!
Use loading screens/timers when necessary
1Jacob Nielsen - 1993
Why do you need to optimize?
Reasons to optimize:
1) Meet time constraints
2) Users complain about apps that run slowly = bad reviews!
3) Inefficient background services use battery
Why is optimizing difficult?
Optimizing mobile applications is difficult because:
• Mobile phones have less compute resources than workstations
• Different mobile devices with various specifications
• UI- or Event-driven code is harder to profile
• Running on the emulator doesn’t necessarily match theperformance on the device
• Especially if the device has a JIT
Optimizing Android Applications
What are goals for optimization?
The primary goals for optimization are:
• Meet all time constraints
• Use less battery
• Use less cellular data – We already went over this
Optimizing for Performance
Primary focus of this lecture is optimizing for performance
Resources:
• https://developer.android.com/topic/performance
First Principle
Most important design decision?
Algorithm and data structure selection
No performance tip can outrun a bad design decision
Writing Efficient Code
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
Creating an object = Memory allocation
Creating a lot of objects forces garbage collection
Tips for reducing object creation:
• Change method signatures to manipulate existing objects
• Slice multi-dimensional arrays into parallel one-dimension
arrays
• Avoid creating short-term temporary objects whenever possible
Prefer Static
If you don’t need to alter an object’s fields – make method static
Invocations will be 15-20% faster
Good coding practice anyway – method signature indicates the
object can’t be manipulated
Use Static Final for constants
• Only applies to primitives and String constants
• Reduces initialization and access time
Use Enhanced For Loop Syntax
The enhanced for loop (or
for-each loop) can be used for
Iterable collections and arrays
Zero is slowest
One is slower than Two without
a JIT
Equivalent with a JIT
Package Access for Private Inner Classes
Accesses to private
values/methods from inside
private inner classes occur
thorough static accessor methods
Performance overhead to use
accessor methods
Use package level instead of
private when not sensitive
Avoid using Floating Point
Rule of Thumb: Floating point is 2x slower than integer on
android devices
In terms of speed, float and double are equivalent
Double is 2x larger in memory
If space isn’t an issue and you require float, use double over float
Along those lines – Avoid divide if possible
Many devices lack a hardware divider
Know and Use Libraries
Library code is likely safer and more optimized than hand-written
code
The system can replace library calls with hand-coded assembler
Using System.arraycopy() is 9x faster on a Nexus One with JIT
than a hand-coded copy loop
Native Methods
Using the Java Native Interface may or may not produce
performance gain
Will require compilation on each architecture the code will run on
Often, the JIT will optimize code equal-to or better than
hand-written code
For more on the JNI with Android:
https://developer.android.com/training/articles/
perf-jni.html
Performance Myths
Invoking methods with an exact typed variable is more efficient
• Slightly true for devices without a JIT
Caching field accesses is faster
• About 20% faster without JIT
• About the same with a JIT
Measure your performance
Before starting to micro-optimize, make sure you have a problem
to solve
Accurately measure existing performance and the goal
Traceview can be useful for profiling
BUT– Traceview currently disables existing JITs, and may
misattribute time
Measuring Performance
Tools to measure performance
Tools:
• Traceview
• Hierarchy View
• Memory Monitor (deprecated)
• Method Tracer (deprecated)
• Android Profiler (Android Stuido 3.0)
Traceview
Traceview –Provides graphical representation of trace logs
Traces generated by instrumenting code with the Debug class
Generating Trace Files
Debug.startMethodTracing() + Debug.stopMethodTracing()
Logs trace data form start->stop
Requires external write permission
startMethodTracing(filename) can be used to create named
tracefiles
Log files are by default stored in getExternalFilesDir()
Hierarchy View
Use to locate an examine view elements within current application
Android Profiler
Android Profiler – New to Android Studio 3.0
Replaces functionality of previous monitoring tools
Advanced Profiling
If running API 25 or lower, you need to enable advanced profiling
Enables:
• The event timeline on all profiler windows
• The number of allocated objects in Memory Profiler
• Garbage collection events in Memory Profiler
• Details about all transmitted files in Network Profiler
Advanced profiling does slow speed (especially involving JIT)
Enabling Advanced Profiling
How to enable Advanced Profiling:
1. Run>Edit Configurations
2. Select app module in left pane
3. Click Profiling Tab
4. Check Enable Advanced Profiling
CPU Profiler
CPU Profiler – Monitor Application CPU usage at macro level
(For detail, record method traces)
CPU Profiler
1. Event Timeline – UI Events
2. CPU Timeline – Real time CPU Usage
3. Thread Activity Timeline – Each thread and activity
4. Recording Configurations – Sampled/Instrumented
5. Record Button – Starts/stops recording a method trace
Memory Profiler
Memory Profiler – Identify memory leaks and churn
Shows real-time graph of application memory use
Can capture a heap-dump, force garbage collection, track memory
allocation
Memory Profiler
1. Force Garbage Collect
2. Capture Heap Dump
3. Record Memory Allocation
4. Zoom in/out of timeline
6. Jump forward to live
memory data
7. Event Timeline
8. Memory Use Timeline
Network Profiler
Network Profiler – Display and inspect realtime network activity
Examine how/when app transfers data in order to optimize
Network Profiler
Network Profiler
Inspecting GPU Rendering
To achieve 60 frame per second, GPU should be drawing approx.
every 16ms
You can view GPU rendering graph on the device
Settings >Developer Options >Monitoring >Profile GPU
Rendering
Select “On Screen as Bars”
Open App you want to profile
Inspect GPU Rendering
Inspect Battery Usage
Battery Historian – Docker image which uses device logs of battery
usage