do with the… brain… • Eye is streaming visual signals, stop motion is a hack • 12fps… and we have motion • 24fps… cheap fluidity • 60fps… the sweet spot • Managing Memory • Preserving Battery • Saving Data
Traceview Insight FIX but don’t rush! Action Performance Lifecycle My app has issues? What can I do?? • Most developers don’t think about performance until it has already become a problem!
when the user wants data and the network returns it • Single biggest battery drain! • More data transferred => bigger cost for the user (metered networks) • Things you can’t control • Bandwidth • Latency • Cellular connection speed • Things you can control/optimize • Radio active time • Number of requests • Data per request (at least try…)
to do • Just do it • Stuff server needs to update • FCM, data update notification • Stuff needs to be updated frequently • AlarmManager • SyncAdapter • JobScheduler (21+) • GcmNetworkManager (PlayServices 7.5)
fast as possible… every sec! • Bottleneck!! • Multiple pending requests • Multiple useless UI updates • Mmmm ok… why not check network first? • Best case interval • Adaptive intervals • No repeated scheduling • Evaluate response times
going to need and fetch • E.g. user settings, common app data • What does this have to do with networking performance? • Each radio request has overhead • Load data when executing another mandatory request • E.g. after login load account related data • Tricky balancing problem
• The more battery consumed • The more cost for the user • JSON and XML (XML? Really??) • Human readable formats -> bloated • Minification • E.g. rates 43 entries • XML = ~7KB • JSON= ~6KB • Minified JSON = ~2KB • Protocol buffers • FlatBuffers
a new single threaded process -> Main/UI thread! • 16ms for main thread to respond to • UI Drawing • System Events • Input Events • Application • Service • Alarm • Offload as much work as possible! {Our Code}
tasks run in a dedicated thread • HandlerThread • Long running thread that grabs work from a queue and operates on it • Thread pool (Executor) • Handles all heavy lifting of parallel processing • IntentService • Kind of hybrid between Service and HandlerThread • The Service misconception • Not a background task • Creating/Scheduling/Running/Destroying services cost time and memory • Without proper handling a service could live forever
the lifecycle • Foreground group • Background group • New threads take the same priority as the spawning thread • THREAD_PRIORITY_DEFAULT • Waste CPU time • Explicit priority • Process.setThreadPriority() • AsyncTask and IntentService do that by default
thread • Activities (and views) can be destroyed at any time • Memory leaks (in a bit) • Work for nothing • Decouple background tasks from UI as much as possible • A good place to cache
are using • Retrofit for convenience return callbacks in main thread • But I have more work that needs to be done • Return to main manually • How to check my thread?
no longer needed but has reference that don't allow it to be garbage collected • Chain leaks • Fill memory heap • Cause more GC events • Consume precious CPU time • Drop frames
widgets • Not enough in many cases • Create a custom view with caution • Be aware of your onDraw • Avoid allocations • Avoid long running code • Only draw what is necessary • Avoid unnecessary invalidations
a bad thing • Decide where carefully • View with real time updates • Small lags when scrolling • User review that app has lags • Disable invalidation when scrolling • User changes review… the app now is blazing fast • Same with images • Load smaller resolution if only meant for thumbnails
need to • Don’t allocate memory if you can avoid • Avoid creating unnecessary objects • Prefer static methods • 15-20% faster • Use static final for constants • Know your platform • Prefer API methods than doing by yourself • Proposed for Java doesn’t mean it work best on Android
Extra logic for chaining etc • ArrayMap<K,V> instead • Better memory use • Slower addition/deletion/retrieval • Faster iteration • When to use? • <1000 items and lots of accesses infrequent insertions/deletions • Maps of maps with many iterations
used by generic collections at runtime • Autoboxing converts from primitives to their respective objects • Unboxing to retrieve the underlying primitive • HashMap<Integer, V> accessed via int • Autoboxing on every action • New allocation • Unboxing logic • 16bytes for Integer rather than 4 for int • SparseArray<V> instead • Pros/cons of ArrayMap • No autoboxing/unboxing
with memory allocation • One not a big deal but within other iterations?? • next() function adds additional logic • Android platform team is supposed to have a policy to avoid Iterators • Lets test this… • Nexus 5 • Android 6.0.1 • 500K random integers in ArrayList • Avg of 10 time run Iteration Time (ms) while (it.hasNext()) 530 for (int i = 0; i < integers.size(); i++) 533 for (int i = 0; i < size; i++) 296 for (Integer i : integers) 529
the app loads, Android will allocate a dedicated memory space • All DEX code is loaded into this • The bigger the DEX, the lowest the memory for the runtime allocations • Why Enums are such an issue? • Enums bloat DEX files end eat up heap space • E.g. 3 states • With static final int: +124bytes • With Enum: +1632bytes (13x more) • Additional runtime overhead • @IntDef and @StringDef
most problems but the little things that when added together create huge headaches Tools not rules In the end what’s important is to understand the trade-offs and know the difference to make informed decisions