100
Performance Matters +Ran Nachmany @shed2k

Android Performance Matters - Ran Nachmany, Google

Embed Size (px)

Citation preview

Performance Matters

+Ran Nachmany@shed2k

Battery PerformanceHey, do you have a power outlet I can use?

I’m doing stuff!

LOL!NOPE.

What’s eating your mobile battery?goo.gl/nMkSE

25-30%Actual work.

70%Analytics

GPSAds

QUIT BEING STUPID.

Better Battery Golden Rule

DEFER WORK UNTIL THE BEST TIME FOR BATTERY

Better Battery Golden Rule

Battery Problem:

WakeLocks

Active Screen Off

ZZ

Z

Asleep

Keeping the device awakegoo.gl/uEfy56

ZZ

Z

Wakelock

Wakelock.aquire(..)goo.gl/ZNCx6n

AlarmManager.setInexact*(..)goo.gl/l7m7fb20 minutes

15 minutes

Release Wakelocks.Batch Wakeups.

#PERFMATTERS TIP

Battery Problem:

Location

EXPENSIVE

GPS Provider Cell Network Provider

More AccurateMore Power

Less AccurateLess Power

GPS Fetch Totally

steal

Passive Provider

Only use the resolutionyou need.

#PERFMATTERS TIP #43

Networking

Battery Drain

Bandwidth

Power

Idle

DCH

FACH

Bandwidth

Power

Idle

DCH

FACH

Tail Time~10 sec

Tail Time~60 sec

Wake Up Time~2 Sec

$$$$$$$$$

User Pays for your requests

LESS RADIO TIMELESS DATA

NETWORKING Golden Rule

Network Technique:

Batching

XHR

wai

t

XHR

wai

tXH

Rw

ait

XHR

wai

t

XHR

wai

t

XHR

wai

t

XHR

XHR

XHR

XHR

XHR

XHR

wai

t

BATCHING!

Do Now Server Response Data Push

Types of networking requests

CAN OPTIMIZE

requ

ests

pending queue

Length == 10

pending queue

requ

ests

Get Notified

Get Notified

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

JobId

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

Job Endpoint

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

Network Type

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

Timing Constraint

JobInfo uploadJob = new JobInfo.Buildr(mSomeInt, mServiceComponent) .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) .setOverrideDeadline(DateUtils.HOUR_IN_MILLIS) .setRequiresCharging(true) .build();

JobScheduler API

Extra Constraint

SyncAdapters

Pre L Batching

SyncAdapters

Pre L Batching

GcmNetworkManager

// Schedule a task to occur between five and fifteen minutes from now: OneoffTask myTask = new OneoffTask.Builder() .setService(MyGcmTaskService.class) .setExecutionWindow( 5 * DateUtil.MINUTE_IN_SECONDS, 15 * DateUtil.MINUTE_IN_SECONDS) .setTag("test-upload") .build(); GcmNetworkManager.get(this).schedule(myTask);

GcmNetworkManager

GcmNetworkManagerhttps://goo.gl/hTwIEt

// Implement service logic to be notified when the task elapses: MyUploadService extends GcmTaskService { @Override public int onRunTask(TaskParams params) { // Do some upload work. return GcmNetworkManager.RESULT_SUCCESS; } }

GcmNetworkManager

GcmNetworkManagerhttps://goo.gl/hTwIEt

// Implement service logic to be notified when the task elapses: MyUploadService extends GcmTaskService { @Override public int onRunTask(TaskParams params) { // Do some upload work. return GcmNetworkManager.RESULT_SUCCESS; } }

GcmNetworkManager

adb shell am broadcast -a "com.google.android.gms.gcm.ACTION_TRIGGER_TASK" \

-e component -e tag

GcmNetworkManagerhttps://goo.gl/hTwIEt

Network Technique:

Prefetching

10 seconds

6 seconds

Fetc

h 1M

B

Fetc

h 1M

B

Fetc

h 1M

B

Fetc

h 1M

B

Fetc

h 4M

B

PRE FETCHING!

wai

t

wai

t

wai

t

wai

t

wai

t

@ Startup

How much do we prefetch?Quality pre-fetch is :

about 1-5mb of data.about 1-2 minutes of data need

2G = fetch 3 new photos

4G = fetch 12 new photos

Network Problem:

Payload Size

45kquality : 70

164kquality : 100

Site JPG QualityGoogle Images Thumbnails 74-76

Facebook full-size images 85

Yahoo frontpage JPEGs 69-91

Youtube frontpage JPEGs 70-82

Wikipedia images 80

Windows live background 82

Twitter user JPEG images 30-100

READ

goo.gl/skf1gp

JSONIS

HORRIBLE

{ "id": 1, "jsonrpc": "2.0", "total": 1, "max_id":276372795494133760, "result": [ { "id": 0, "guid": "2084d344-81fe-4714-9e2a-42c83b46083b", "isActive": true, "balance": "$1,507.00", "picture": "http://placehold.it/32x32", "age": 24, "latitude": -85.791587, "longitude": -64.615557, "tags": [ "quis", "est", "ea", "velit", "exercitation", "quis", "veniam" ], "friends": [ { "id": 0, "name": "Sanford Patton" }, { "id": 1, "name": "Tameka Frazier" }, { "id": 2, "name": "Gilliam Leach" } ], "randomArrayItem": "apple" } ]}

Spaces, quotes, returns, names, are all

verbose data.

{ "id": 1, "jsonrpc": "2.0", "total": 1, "max_id":276372795494133760, "result": [ { "id": 0, "guid": "2084d344-81fe-4714-9e2a-42c83b46083b", "isActive": true, "balance": "$1,507.00", "picture": "http://placehold.it/32x32", "age": 24, "latitude": -85.791587, "longitude": -64.615557, "tags": [ "quis", "est", "ea", "velit", "exercitation", "quis", "veniam" ], "friends": [ { "id": 0, "name": "Sanford Patton" }, { "id": 1, "name": "Tameka Frazier" }, { "id": 2, "name": "Gilliam Leach" } ], "randomArrayItem": "apple" } ]}

Copied into memory, must determine if

string, int, date, etc.

FlatBuffers

FlatBuffers

Scheme Compiler

.java

.cpp

.goFlatBuffershttp://goo.gl/r9xTXK

Smaller datawins the Internet.

#PERFMATTERS TIP #9

Memory PerformanceWHY IS EVERYTHING SLOW????? I FORGET……...

GC Event!

Allo

cate

d m

emor

y

Memory Threshold

Fib3(..) GC Fib3(..)Mainfunction

FIB3 fcn haulted

FIB3 fcn Resume

16ms

DRAW!DRAW! DRAW!

16ms 16ms

UPDATE GC

GC events eat kittens

framerate

MEMORY Golden Rule

Memory Problem:

Bitmaps

HEA

P

IMGIMG

GC

IMGIMG

HEA

P

Smaller Pixel Formats

Down-ScaleImagesBitmap Re-use

Glidegoo.gl/flNbyf

Picassogoo.gl/tpTc1

Bitmaps are bigMake them smaller

#PERFMATTERS TIP #44

Memory Problem:

HashMap

KEY

Hash-to-index

Allocated, but unused

Allocated, but unused

Stored Value

ArrayMap.javagoo.gl/SCeQEL

ArrayMap

HASH #1

HASH #2

HASH #3

Hashes of keyssorted

VALUE 2

KEY 3

VALUE 3

KEY 1

VALUE 1

KEY 2

Interwovenkey / value

ArrayMap.javagoo.gl/SCeQEL

HASH #8

HASH #9HASH #10

KEY HASH #5

HASH #6

HASH #7

HASH #1

VALUE 7

KEY 8

VALUE 8

KEY 1

VALUE 1

KEY 7

Key Index = (hashIndex *2) + 1

binary search

HASH #7

collision search

VALUE 7

KEY 8

VALUE 8

KEY 1

VALUE 1

KEY 7

Key Index = (hashIndex *2) + 1

HASH #8

HASH #9HASH #10

KEY HASH #5

HASH #6

HASH #7

HASH #1binary search

EmptyBut array still allocated

Emptynothing allocated

HashMap ArrayMap

<1000objects

Mapscontaining maps

Use ArrayMapin the right places.

#PERFMATTERS TIP #76

Memory Problem:

Auto Boxing

Primitive sizes

boolean 8 bits

int

float 32 bits

32 bits

boolean java.lang.Boolean

int

float java.lang.Float

java.lang.Integer

Integer value = 0

Primitive int

Integer Object

Autoboxing

// Primitive versionint total = 0;for (int i = 0; i < 100; i++) total += i;

// Generic versionInteger total = 0;for (int i = 0; i < 100; i++) total += i;

// Primitive versionint total = 0;for (int i = 0; i < 100; i++) total += i;

// Generic versionInteger total = 0;for (int i = 0; i < 100; i++) //total += i;

Allocates 83 new objects!(yea, i know, it’s confusing..)

Allocates 0 new objects!

// create new Integer(), // push in new value // add to total

HashMap <Primitive,Object>

put update get

autoboxing autoboxingautoboxing

HashMap <obj, obj>

SparseBoolMap <bool,obj>

SparseIntMap <int,obj>

SparseLongMap <long,obj>

LongSparseMap <long,obj>No

Auto

boxi

ng

Lots

of G

ener

ics

Single Call Site

AllocationTracker

Memory Profiling 101goo.gl/h1Cl9k

TraceView

Avoid Autoboxing

#PERFMATTERS TIP #21

Memory Problem:

ENUMs

2556Bytes

public static final int VALUE1 = 1;public static final int VALUE2 = 2;public static final int VALUE3 = 3;

int func(int value) {switch (value) {

case VALUE1:return -1;

case VALUE2:return -2;

case VALUE3:return -3;

}return 0;

}Bytes

2680

+124 bytes

public static enum Value {VALUE1,VALUE2,VALUE3

}int func(Value value) {

switch (value) {case VALUE1:

return -1;case VALUE2:

return -2;case VALUE3:

return -3;}return 0;

} Bytes4188

13x more than int version

public static enum Value { VALUE1, VALUE2, VALUE3 }

12-16 bytesfor the array

20+ bytes (each)

If you’re using ENUMSSTOP.

#PERFMATTERS TIP #73

QUIT BEING STUPID.

#PerfMatters Golden Rule