Shared publicly  - 
 
I have posted slides from my talk "Eliminating Code Overhead" which I gave yesterday at Square.

By themselves, these slides are sparse on any explanation or reasoning for what's on them. The event was recorded and a video of me blabbering over them will be made available later.

The CPU, RAM, and disk are finite resources that are often taken for granted as unbounded. Not only is this obviously untrue, but the use of these resources directly affects the most important resource on a mobile device: the battery. This talk will focus on techniques that both libraries and applications can implement to ensure their effect is in general without overhead.

#AndroidDev
The CPU, RAM, and disk are finite resources that are often taken for granted as unbounded. Not only is this obviously untrue, but the use of these resources directly affects the most important resource on a mobile device: the battery. This talk will focus on techniques that both libraries and applications can implement to ensure their effect is in general without overhead. Video: Coming soon!
240
133
Marty Glaubitz's profile photoLe Hoang Tu's profile photoChristopher Jenkins's profile photoLindelwe Ncube's profile photo
26 comments
 
+Jake Wharton thanks! I thought your talk was great and I've found myself making some of the types of optimizations you talked about already.  Also going to be checking out LeakCanary which sounds super useful. It's awesome that Square makes open source work and sharing knowledge like this such a priority. 
 
Slides are pretty self-explanatory, sometimes even too self-explanatory. :)
+1
 
I've got a question. Isn't the compiler do some of those optimizations by itself?

For example the getResources() one
 
Small details to be looked into in detail or we loose optimization. Great talk.
 
Don't modern Java compilers do some of these optimizations automatically (that's a real question) ?
 
+Michael Pujos javac does none of these. The JIT or AOT compiler and the VM runtime can do method inlining and potentially cache method table lookups, but it relies on being able to detect these cases and have them invoked enough. Even then, in the case of calling getResources() once and storing the reference in a local will always be faster than any optimizations that can be made.
 
+Jake Wharton Do you have performance gains measurements for these optimizations? I have noticed that when encouraging a switch to more performant structures, engineers tend to question their usefulness. Even if they understand that certain approach provides gains, they might consider it not worth it because of readability/maintainability cost. It would be very useful to know the exact impact, and how it affects larger projects.
 
Also, Proguard has various optimizations (like inlining methods, merging classes). Did you try using them beside just stripping methods?
 
Great slides. I would have put that ".tmp" outside the for loop or in a static final String outside the method because in the slides it's creating a new String object for every loop iteration. 
 
The entire "dont't use enums on android..." is really bugging me... right from the beginning i thought "man this sounds like pre-mature optimization...". I mean can't the VM/ART optimize the overhead away?! Do we still have to use ints as flags as if we were coding in C?!....
 
+Mathieu Méa​ Strings are interned in a pool so it reuses the same instance. Moreover, putting it in a static final field allows javac to inline the field so the byecode would be exactly the same as if it were just referenced as I had it.
 
+Filip Gruszczyński​ The only example driven by tooling was the implicit double StringBuilder one. We found that with allocation tracker and measured the difference after the fix.

For all the others, the wins are obvious but hard to measure. Doing something once rather than 5 or list.size() times will always be better. I prefer to look at it as a win on byte codes executed, jumps necessary, and memory lookups reduced rather than with hard numbers. Can you reason about what a 100ns improvement does to your code? I can't, but I can apply the cached-count for loop pattern and know that it adds up to non-zero in the long run. It's enough for me, at least.
 
+Jake Wharton​ at Facebook we find ourselves making pretty heavy usage of Caliper 0.5 (1.0 was broken on Android) for verifying these wins. It's of course got all the caveats of microbenchmarking but it generally does a good job convincing our team that things like the RandomAccess-based iteration is far superior to the iterator approach.
 
+Yoav Sternberg I don't think the compiler is that clever. As it would need to assume every call to getResources() would return the same object, in this case it would, but as a use case elsewhere, no. 
 
Still have no idea when the video will arrive?
Add a comment...