40. “With Instant Apps, tapping a link can take you with Deep
Links into an Android app in just a few seconds without
having to install the app,”
Michael Siliski
46. Theory
A
“Understanding is the first step to acceptance,
And only with acceptance can there be recovery.”
J. K. Rowling, Harry Potter and the Goblet of Fire
47. - Assess the problem and
establish acceptable behavior.
- Measure perf b4 modification.
- Identify bottleneck.
- Remove bottleneck.
- Measure perf after modification.
- If better, adopt.
If worse, put it back.
Methods of Systematic performance improvement
https://en.wikipedia.org/wiki/Performance_tuning
- Figure Out Where You Need to Be
- Determine Where You Are Now
- Decide Whether You Can Achieve
Your Objectives
- Develop a Plan for Achieving Your
Objectives, and Execute
- Conduct an Economic Analysis
http://www.perfeng.com/papers/step5.pdf
49. Meet Prof. Donald Kunth
Professor at Stanford, Wrote “The art of computer programming”
Few quotes:
“Beware of bugs in the above code;
I have only proved it correct, not
tried it.”
https://en.wikipedia.org/wiki/Donald_Knuth
50. Meet Prof. Donald Kunth
https://en.wikipedia.org/wiki/Donald_Knuth
Professor at Stanford, Wrote “The art of computer programming”
Few quotes:
The psychological profiling [of a
programmer] is mostly the ability to
shift levels of abstraction,
from low level to high level.
51. Meet Prof. Donald Kunth
https://en.wikipedia.org/wiki/Donald_Knuth
Professor at Stanford, Wrote “The art of computer programming”
Few quotes:
Programmers waste enormous amounts of time thinking about, or
worrying about, the speed of noncritical parts of their programs, and
these attempts at efficiency actually have a strong negative impact
when debugging and maintenance are considered.
We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil. Yet we should
not pass up our opportunities in that critical 3%.
52. However...
Knowing these kind of things
- Helps you avoid mistakes and bugs
- Makes you a better developer
- Teaches you the internal workings of the system
- Cost-Effectiveness-wise it’s just being smart:
“...Yet we should not pass up our opportunities in that critical 3%”Colt McAnlis: https://medium.com/google-developers/the-truth-about-preventative-optimizations-ccebadfd3eb5
53. Target Audience
This lecture is for you if…:
- You have a custom view in your app
- You have a lot of images in your app
- You have an app, or developing an app,
and want to do a better job
- You want to become a better developer
57. Step 0: Inflate the View Tree
- During onCreate() we call setContentView()
- The XML is parsed
and a tree of objects is created
- The tree is traversed during next
steps
58. Now we have
a Data Structure to use
Things get interesting!
59. Step 1: Measure
- Starts with the root
- Recursively ask the views (+Children) to measure themselves.
- This is done by calling onMeasure(int, int)
- It’s a negotiation, so onMeasure may be called multiple times.
- When it’s done, All the views in the tree know their size.REF: http://developer.android.com/reference/android/view/View.html#onMeasure(int, int)
60. Step 2: Layout
- Starts with the root
- Recursively position each child
- Done by onLayout(boolean, int, int, int, int)
- Stores the position, and set position for all children
- When it’s done, All the views in the tree knows their positionREF: http://developer.android.com/reference/android/view/View.html#onLayout(boolean, int, int, int, int)
61. - Now that a view knows its position,
The onDraw(Canvas) method is called
- That’s where a view draws itself
before asking its children to draw.
- The Canvas object generates (or Updates) a list of OpenGL-ES
commands (draw-list) to send to the GPU.
Step 3: Draw (AKA Update)
REF: http://developer.android.com/reference/android/view/View.html#onDraw(android.graphics.Canvas)
Guide: http://developer.android.com/training/custom-views/custom-drawing.html
64. Plus ça change, plus c'est la même chose
When things change (text, color, size, padding, margin, etc.),
A view notifies the system, by calling
Invalidate - which will call the onDraw again, or
requestLayout - which will call the entire process again.
67. Step 4: Execute
The GPU executes the command list,
That was generated in onDraw()
And was cached
But what if this takes too long?
68.
69. Solution: Use a double buffer
http://openglbook.com/chapter-1-getting-started.html
70. Solution: Use a double buffer
http://openglbook.com/chapter-1-getting-started.html
71. Step 5: VSync
Old CRT screens had to be “synced”,
so that the monitor starts a frame
at the correct time.
Similarly, Android holds the copy from a back buffer
if it is currently drawing to the screen.
https://en.wikipedia.org/wiki/Analog_television#Vertical_synchronization
74. But How Does It Work?
Smooth
Motion
60
No
Difference
60+
Flip Book
12
Movies
Frames Per Second
Fluid Motion
24
+effects
75. We Have A Winner!
Smooth
Motion
60
No
Difference
60+
Flip Book
12
Movies
Frames Per Second
Fluid Motion
24
+effects
Smooth
Motion
60
Colt McAnlis: https://youtu.be/CaMTIgxCSqU
76. Things to remember
- Britt will give a similar explanation on her lecture on 13/6
- Know thee process,
Appreciate, and
Know that the entire process should take less than 16ms
- Things on the GPU:
- Should get there as soon as possible (early)
79. Few things in this process can go wrong
- Allocations in onDraw()
- A reminder from last week
- Avoiding Redundant Work
- Overdraw
- ClipRect
- QuickReject
- Invalidations
80. Allocating objects (new XXX()) might cause a GC (blocking)
So you might drop a frame.
Allocations in onDraw()
But it goes much deeper. See Ian Ni-Lewis: https://youtu.be/HAK5acHQ53E
81. Solution and Avoidance
Solution: DON’T ALLOCATE OBJECTS IN onDraw() METHOD.
Avoidance: USE LINT (built into the Studio)
https://developer.android.com/studio/write/lint.html || Colt McAnlis: https://youtu.be/Z_huaXCsYyw
STUDIO
87. GPU Profiling
Displays a graph for each visible app, showing
how much time each frame took:
The taller the bar, the longer it took
to render
The green line marks the 16 millisecond target.
Every time a frame crosses it,
your app is missing a frame.
https://developer.android.com/studio/profile/dev-options-rendering.html
93. This is where you tell them the biggest lie of the GPU profiler,
Before moving to the next part
BTW - Now for reals,
Any questions?
94. B
The number of files that a given pixel is
drawn in a frame.
Overdraw
Colt McAnlis: https://youtu.be/T52v50r-JfE
95. What is Overdraw
When a pixel is drawn multiple times -
That’s overdraw.
it might waste time and energy.
When the GPU executes the display list,
It can count how many times each pixel is drawn.
Not like this
100. Fixing Overdraw
There are 2 common reasons for overdraw:
- Redundant backgrounds / Redundant transparency
- Wasteful onDraw
- Things that aren’t visible at all gets drawn (not using quickReject)
- Things that will be overdrawn gets drawn (not using clipRect)
Colt McAnlis: https://youtu.be/vkTn3Ule4Ps
101. QuickReject
A method to tell if something can be not drawn at all.
Call quickReject to see if you can skip drawing of things that will be
off screen.
REF: https://developer.android.com/reference/android/graphics/Canvas.html
102. ClipRect
ClipRect is a way to avoid OverDraw,
By keeping your GPU from drawing pixels that you know that will be
obscured by other stuff,
you refrain from overdraw.
104. ClipRect vs. QuickReject
Method return type: Detects... Helps to...
QuickReject boolean Fully invisible stuff Avoid redundant
calls to drawXXX(),
Keeping the
drawlist short.
ClipRect void Fully and Partially
invisible stuff
Avoid drawing
pixels,
but still executing
the draw-list!
boolean
But is usually used
as void
108. Plus ça change, plus c'est la même chose
When things change (text, color, size, padding, margin, etc.),
A view notifies the system, by calling
Invalidate - which will call the onDraw again, or
requestLayout - which will call the entire process again.
110. The horrible things that we do with
bitmaps are incredible,
but there are ways to fix it!
Bitmap Abuse
D
111. Bitmaps flow
Nothing here is accurate, but as an overview, it’s OK.
Image stored in the
APK, or in media
pack
Image downloaded
from internet, kept in
device storage
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
112. Bitmaps flow
Nothing here is accurate, but as an overview, it’s OK.
Image stored in the
APK, or in media
pack
Image downloaded
from internet, kept in
device storage
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
Uses PNG or JPEG
formats, files are
stored compressed
Optimized by AAPT
Uses one of 4 formats:
ALPHA_8 1 byte per pixel, only
alpha
ARGB_4444 deprecated
ARGB_8888 4 bytes per pixel,
+alpha
RGB_565 2 bytes per pixel, no
alpha
113. Bitmaps flow - Downloading
Image stored in the
APK, or in media
pack
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
Image downloaded
from internet, kept in
device storage
Which image format is downloaded?
Which Quality?
Which Size?
Which network? WIFI? Metered?
For how long are these images kept?
Any size limits?
114. Image downloaded
from internet, kept in
device storage
Bitmaps flow - In Package
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
Which image format is stored?
Which Quality?
Which Size(s)?
Which network? WIFI? Metered? → APK SIZE
For how long are these images kept? → Forever
Any size limits? → 100mb, but users will hate you!
Image stored in the
APK, or in media
pack
115. Image stored in the
APK, or in media
pack
Image downloaded
from internet, kept in
device storage
Bitmaps flow - In Memory
Image loaded into GPU
Content is drawn on
screen
What Pixel-Format is used?
Does the image need to re-scale?
How to scale the image efficiently?
Does the image has enough room?
Image loaded into
memory (to the Heap)
116. Image stored in the
APK, or in media
pack
Image downloaded
from internet, kept in
device storage
Bitmaps flow - In GPU
Content is drawn on
screen
Image loaded into
memory (to the Heap)
How much time does it take to copy the image?
Do you causing rendering to another buffer?
Image loaded into GPU
117. Why is it important?
java.lang.OutofMemoryError: bitmap size exceeds VM budget.
Nexus 5x takes pictures at 3840x2160 resolution, at 24-bit.
That’s 33,177,600 bytes of data.
Well, good-luck!
https://developer.android.com/training/displaying-bitmaps/index.html
118. Lucky us,
We can optimize almost everything,
And there’s A LOT of information out there
119. Bitmaps flow - Optimize download
Image stored in the
APK, or in media
pack
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
- Work with your server folks to provide you with
smaller files and better formats
- Use Cache (LRU Cache is great!)
- Use an image handling library, like Glide or Picasso
Image downloaded
from internet, kept in
device storage
120. Image downloaded
from internet, kept in
device storage
Bitmaps flow - Optimize APK size
Image loaded into
memory (to the Heap)
Image loaded into GPU
Content is drawn on
screen
- Choose the right format
- Choose a good-enough quality
- Add PNG/JPEG compression tools to your build
process
- Remove unused resources
Image stored in the
APK, or in media
pack
121. Image stored in the
APK, or in media
pack
Image downloaded
from internet, kept in
device storage
Bitmaps flow - Optimize loading & memory
Image loaded into GPU
Content is drawn on
screen
- Choose the right pixel format
- Resize
- Load on non-UI thread
- Reuse memory
- Use object pools if needed
Image loaded into
memory (to the Heap)
122. Most Important Tip:
Use a good image handling library
and let’s check out *some* of the other things that we can do
123. Trick #1: Load images efficiently
Step 1:
Don’t load the image at all,
Only decode its size.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
125. Trick #2: Cache and off-load
Use LRU-Cache to load bitmaps into memory and re-use them.
This will help with list-views and similar, and help to limit the amount
of memory used.
Move things off the UI thread. Use AsyncTask, but with caution, and
handle concurrency, recycling, and lifecycle.
https://developer.android.com/training/displaying-bitmaps/process-bitmap.html
https://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
126. Trick #3: Re-use bitmaps, in pools
- Supported from 3.0 (API 11)
- if possible, use the same memory.
- Works only on mutable bitmaps (BitmapFactory.Options)
- Works only if image size is smaller than the buffer (since KitKat,
4.4)
Works only if image sizes are exactly the same (before)
- Not easy work
Colt McAnlis: https://youtu.be/_ioFW3cyRV0 , and https://developer.android.com/training/displaying-bitmaps/manage-memory.html
127. Trick #4: Be smarter than AAPT with PNGs
AAPT optimizes PNG files - but uses only these 3 optimizations:
- Is the image Grayscale
- Is the image Transparent
- Is the image cheap to index
All loss-less optimizations.
Apply a lossy optimization tool.
128. Trick #4: Be smarter than AAPT with PNGs
You will probably want some more info.
PNG:
How it works: https://medium.com/@duhroach/how-png-works-
f1174e3cc7b7
Reducing size: https://medium.com/@duhroach/reducing-png-file-size-
8473480d0476
AAPT: https://medium.com/@duhroach/smaller-pngs-and-android-s-aapt-tool-
4ce38a24019d
JPG:
How it works: https://medium.freecodecamp.com/how-jpg-works-
a4dbd2316f35
Reducing size: https://medium.com/@duhroach/reducing-jpg-file-size-