Optimizing Apps for Better Performance

Post on 06-Apr-2017

1.298 views 4 download

Transcript of Optimizing Apps for Better Performance

Optimizing Apps for Better Performance

Elif BoncukSoftware Specialist @ Garanti Teknoloji

#dfist

Who am I?

➢Hacettepe - Computer Engineering (2006 - 2011)➢Garanti Technology - Mobile Applications Team (2011- )➢MBA Student @BAU (2014 - )➢Blogger (2010 - )➢Photographer

@elifbon_+ElifBoncukwww.elifboncuk.wordpress.com

#dfist

Be Faster!

➢Gather Information➢Gain Insight➢Take Action

#dfist

4 Major Steps

➢Rendering➢Compute➢Memory➢Battery

#dfist

Rendering

Udacity: Android Performance

#dfist

Rendering...

Udacity: Android Performance

#dfist

Rendering...MEASURE

EXECUTE

RECORD

LAYOUT

CPU

RASTERIZATION GPU

FLOW

PROBLEM

OVERDRAW

LAYOUTS & INVALIDATIONS

PROBLEM

#dfist

Rasterization

Udacity: Android Performance

#dfist

Overdraw

➢ Overdraw is a term used to describe how many times a pixel on the screen has been redrawn in a single frame.

Udacity: Android Performance

#dfist

Overdraw...

1. On your mobile device, go to Settings and tapDeveloper Options.

2. In the Hardware accelerated rendering section, select Debug GPU

Overdraw.

3. In the Debug GPU overdraw popup, select Show overdraw areas.

4. Don't panic as your screen turns into a delirium of colors. The coloring

is provided to help you diagnose your app's display behavior.

http://developer.android.com/

#dfist

Overdraw…

5. The colors are hinting at the amount of overdraw on your screen

for each pixel, as follows:

True color: No overdraw

Blue: Overdrawn once

Green: Overdrawn twice

Pink: Overdrawn three times

Red: Overdrawn four or more times

http://developer.android.com/

#dfist

Overdraw…

How?

➢Eliminate unneeded backgrounds and drawables

➢Define areas will hide portions of view

Best Practices:

➢getWindow().setBackgroundDrawable(null➢android:background:”@null”

http://developer.android.com/

#dfist

Clipping

➢ Clipping is an optimisation which can be defined as Android framework knows overdraw is a problem and will go out of its way to avoid drawing UI widgets that may be invisible in the final image.

➢ Canvas.quickReject()➢ Canvas.clipRect()

DRAWABLE ZONE

Canvas.clipRect()

20dp

20dp 20dp

20dp

Udacity: Android Performance

#dfist

CPU Optimizations

Udacity: Android Performance

#dfist

Hierarchy Viewer

http://developer.android.com/

#dfist

Hierarchy Viewer

Bird's-eye view

Tree Overview

Tree View

View Properties

Nodes

http://developer.android.com/

#dfist

Hierarchy Viewer

Each view in your subtree gets three dots, which can be green, yellow, or red.

The left dot represents the Draw Process of the

rendering pipeline.

The middle dot represents the Layout Phase.

The right dot represents the Execute Phase.

http://developer.android.com/

#dfist

Hierarchy Viewer

The color of the dots indicates the relative performance of this node in respect to all other profiled nodes.

Green means the view renders faster than at least half of the

other views.

Yellow means the view renders faster than the bottom half of the

other views.

Red means the view is among the slowest half of views.

http://developer.android.com/

#dfist

Compute➢ Slow Function Performance

Udacity: Android Performance

#dfist

Profiling with Traceview

➢ Traceview is a graphical viewer for execution logs that you create by using the Debug class to log tracing information in your code. Traceview can help you debug your application and profile its performance.

#dfist

Profiling with Traceview

http://developer.android.com/

#dfist

Batching and CachingTARGET ARRAY TARGET VALUES

Look at all that overhead!

Udacity: Android Performance

#dfist

Blocking the UI Thread

Udacity: Android Performance

#dfist

How to Solve?

Android's single thread model:

1. Do not block the UI thread

2. Do not access the Android UI toolkit

from outside the UI thread

Udacity: Android Performance

#dfist

How to Solve?public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start();}

public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start();}

#dfist

How to Solve?public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png");}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); }

/** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); }}

#dfist

Analyzing UI Performance with Systrace

➢ The Systrace tool allows you to collect and inspect timing information across an entire Android device, which is called a trace.

Trace.beginSection("Data Structures");// TODO:Trace.endSection();

#dfist

Analyzing UI Performance with Systrace

Bad Performance Example

http://developer.android.com/

#dfist

Analyzing UI Performance with Systrace

http://developer.android.com/

#dfist

Memory

Basic Principles of Garbage Collection:➢ Find data objects in a program that cannot be accesed in the future.➢ Reclaim the resources used by those objects.

Udacity: Android Performance

#dfist

Memory Monitor

Memory Monitor reports in real-time how your app allocates memory.

➢ Showing available and used memory in a graph, and garbage collection events over time.

➢ Quickly testing whether app slowness might be related to excessive garbage collection events.

➢ Quickly testing whether app crashes may be related to running out of memory.

Dark blue: Amount of memory that your app is currently using.

Light blue: Available, unallocated memory.

#dfist

Memory Monitor

#dfist

Heap Viewer

Heap Viewer reports in real-time what types of objects your application has allocated, how many, and their sizes

on the heap.

➢ Getting a sense of how your app allocates and frees memory.

➢ Identifying memory leaks.

➢ 5.0+

http://developer.android.com/

#dfist

Heap Viewer

http://developer.android.com/

#dfist

Allocation Tracker

Allocation Tracker records an app's memory allocations and lists all allocated objects for the profiling cycle with their call

stack, size, and allocating code.

➢ Identifying where many similar object types, from roughly the same call stack, are allocated and deallocated over a very

short period of time.

➢ Finding the places in your code that may contribute to inefficient memory use.

http://developer.android.com/

#dfist

Battery

Udacity: Android Performance

#dfist

Batterystats & Battery Historian

Batterystats collects battery data from your device, and Battery Historian converts that data into an HTML visualization that you can view in your Browser.

➢ Showing you where and how processes are drawing current from the battery.

➢ Identifying tasks in your app that could be deferred or even removed to improve battery life.

➢ 5.0+

#dfist

Batterystats & Battery Historian

http://developer.android.com/

#dfist

Batterystats & Battery Historianbattery_level: When the battery level was recorded and logged.

top: The application running at the top.

wifi_running: Shows that the Wi-Fi network connection was active.

screen: Screen is turned on.

phone_in_call: Recorded when the phone is in a call.

wake_lock: App wakes up, grabs a lock, does small work, then goes back to sleep. running: Shows when the CPU is awake. Check whether it is

awake and asleep when you expect it to be.

wake_reason: The last thing that caused the kernel to wake up. If it's your app, determine whether it was necessary.

mobile_radio: Shows when the radio was on. Starting the radio is battery expensive. Many narrow bars close to each other can indicate opportunities

for batching and other optimizations.

gps: Indicates when the GPS was on. Make sure this is what you expect.

sync: Shows when an app was syncing with a backend.

#dfist

Batterystats & Battery Historian

Battery History: A time series of power-relevant events, such as screen, Wi-Fi, and app launch.

These are also visible through Battery Historian.

Per-PID Stats: How long each process ran.

Statistics since last charge: System-wide statistics, such as cell signal levels and screen

brightness. Provides an overall picture of what's happening with the device. This information is

especially useful to make sure no external events are affecting your experiment.

Estimated power use (mAh) by UID and peripheral: This is currently an extremely rough

estimate and should not be considered experiment data.

Per-app mobile ms per packet: Radio-awake-time divided by packets sent. An efficient app will

transfer all its traffic in batches, so the lower this number the better.

All partial wake locks: All app-held wakelocks, by aggregate duration and count.

#dfist

Batterystats & Battery Historian

Udacity: Android Performance

#dfist

JobScheduler

Google IO 2014: Project Volta

#dfist

JobSchedulerprivate void pollServer() { mWakeLockMsg.setText("Polling the server! This day sure went by fast."); for (int i=0; i<10; i++) { mWakeLock.acquire(); mWakeLockMsg.append("Connection attempt, take " + i + ":\n"); mWakeLockMsg.append(getString(R.string.wakelock_acquired));

// Always check that the network is available before trying to connect. You don't want // to break things and embarrass yourself. if (isNetworkConnected()) { new SimpleDownloadTask().execute(); } else { mWakeLockMsg.append("No connection on job " + i + "; SAD FACE"); } }}

@Overrideprotected void onPostExecute(String result) { mWakeLockMsg.append("\n" + result + "\n"); releaseWakeLock();}

#dfist

JobSchedulermServiceComponent = new ComponentName(this, MyJobService.class);

@Overridepublic boolean onStartJob(JobParameters params) { Log.i(LOG_TAG, "Totally and completely working on job " + params.getJobId()); // First, check the network, and then attempt to connect. if (isNetworkConnected()) { new SimpleDownloadTask() .execute(params); return true; } else { Log.i(LOG_TAG, "No connection on job " + params.getJobId() + "; sad face"); } return false;}

public void pollServer() { JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); for (int i=0; i<10; i++) { JobInfo jobInfo = new JobInfo.Builder(i, mServiceComponent) .setMinimumLatency(5000) // 5 seconds .setOverrideDeadline(60000) // 60 seconds (for brevity in the sample) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // WiFi or data connections .build();

mWakeLockMsg.append("Scheduling job " + i + "!\n"); scheduler.schedule(jobInfo); }}

#dfist

Hunter S. Thompson

“Life should not be a journey to the grave with the intention of arriving safely in a pretty and well preserved body, but rather to skid in broadside in a cloud of smoke, throughly used up, totally worn out, and loudly proclaiming “Wow! What a ride!””

#dfist

Questions?

@elifbon_+ElifBoncukwww.elifboncuk.wordpress.com

Thank you!