Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PERFMATTERS for Android - DroidCon Tunis 2016

PERFMATTERS for Android - DroidCon Tunis 2016

The slogan '#PERFMATTERS' by Colt McAnlis is one of the most important statements, which an Android developer should follow. A well performing application makes the difference between a nice looking application and one, which gets successful. You, as an Android developer, have the responsibility to delight your users, so they don't feel how much work your application has to burden to fulfill the user's needs. This session will show you some easy optimizations and how to avoid glitches in the application. A lot of developers would shout, that this is premature optimization. In contrary it is preventive. With a small amount of work while developing you can avoid a lot of pitfalls. You will hopefully have a better understanding of the underlying system afterwards. During the session some tools and frameworks will be presented for helping you to fulfill your mission.

Hasan Hosgel

March 05, 2016
Tweet

More Decks by Hasan Hosgel

Other Decks in Technology

Transcript

  1. Hasan Hosgel #DroidConTN We love to delight our users Source:

    http://agenciabrasil.ebc.com.br/geral/foto/2014-07/cerimonia-de-premiacao-da-copa-do-mundo-no-brasil
  2. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  3. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  4. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s • 49% app start < 2 s Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  5. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s • 49% app start < 2 s • Users are intolerant of issues and are quick to uninstall mobile apps Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  6. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s • 49% app start < 2 s • Users are intolerant of issues and are quick to uninstall mobile apps • 80% three attempts or less Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  7. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s • 49% app start < 2 s • Users are intolerant of issues and are quick to uninstall mobile apps • 80% three attempts or less • 53% apps with severe issues like crashes, freezes or errors Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  8. Hasan Hosgel #DroidConTN User Expectations • Mobile App Users are

    impatient • 61% app start < 4 s • 49% app start < 2 s • Users are intolerant of issues and are quick to uninstall mobile apps • 80% three attempts or less • 53% apps with severe issues like crashes, freezes or errors • 36% heavy battery usage Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  9. Hasan Hosgel #DroidConTN User Expectations • Users blame the app

    and the company who made it Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  10. Hasan Hosgel #DroidConTN User Expectations • Users blame the app

    and the company who made it • 55% app is responsible for performance issues Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  11. Hasan Hosgel #DroidConTN User Expectations • Users blame the app

    and the company who made it • 55% app is responsible for performance issues • 37% Stated that app crashes or errors make them think less of a company’s brand Source: https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf
  12. Hasan Hosgel #DroidConTN • 500 ms delay • bounce rate

    -4.7% -- conversion rate -1.9% • 1,000 ms delay • bounce rate -8.3% -- Conversion rate -3.5% • 100ms delay mean for Amazon -1% revenue • 11% scream at there device • 4 % throw their phones Performance Impacts Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg http://giphy.com/gifs/reactiongifs-angry-time-1306MTkHlXkUZG http://giphy.com/gifs/homer-simpson-fat-mumu-Sm8Ec3ddRWXa8
  13. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay Source:

    http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  14. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  15. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% • 1,000 ms delay Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  16. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% • 1,000 ms delay • bounce rate -8.3% -- Conversion rate -3.5% Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  17. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% • 1,000 ms delay • bounce rate -8.3% -- Conversion rate -3.5% • 100ms delay mean for Amazon -1% revenue Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  18. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% • 1,000 ms delay • bounce rate -8.3% -- Conversion rate -3.5% • 100ms delay mean for Amazon -1% revenue • 11% scream at there device Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg
  19. Hasan Hosgel #DroidConTN Performance Impacts • 500 ms delay •

    bounce rate -4.7% -- conversion rate -1.9% • 1,000 ms delay • bounce rate -8.3% -- Conversion rate -3.5% • 100ms delay mean for Amazon -1% revenue • 11% scream at there device • 4 % throw their phones Source: http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive-Design-vs-Server-Side-Solutions- Infographic.jpg https://www.flickr.com/photos/9009139@N08/1263954439
  20. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Keep

    the work of the main thread  ANR • Avoid GPU overdrawings
  21. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Keep

    the work of the main thread  ANR • Avoid GPU overdrawings • https://www.youtube.com/watch?v=T52v50r-JfE
  22. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Keep

    the work of the main thread  ANR • Avoid GPU overdrawings • https://www.youtube.com/watch?v=T52v50r-JfE • Avoid nested multi-pass layouts
  23. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Keep

    the work of the main thread  ANR • Avoid GPU overdrawings • https://www.youtube.com/watch?v=T52v50r-JfE • Avoid nested multi-pass layouts • http://goo.gl/Q5te24
  24. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Keep

    the work of the main thread  ANR • Avoid GPU overdrawings • https://www.youtube.com/watch?v=T52v50r-JfE • Avoid nested multi-pass layouts • http://goo.gl/Q5te24 • Consider RenderScript for performance critical code
  25. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Do

    not allocate memory inside onDraw() • Avoid Leaks
  26. Hasan Hosgel #DroidConTN Setup LeakCanary debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1’ build.gradle

    public class DcTnApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } } DcTnApplication.java
  27. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Do

    not allocate memory inside onDraw() • Avoid Leaks • Avoid listener  EventBus
  28. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Do

    not allocate memory inside onDraw() • Avoid Leaks • Avoid listener  EventBus • Use SparseArray* family instead of JDK Collections/ Maps
  29. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Do

    not allocate memory inside onDraw() • Avoid Leaks • Avoid listener  EventBus • Use SparseArray* family instead of JDK Collections/ Maps • Be aware that enums need more resource, but use them, if it will make sense for you
  30. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Activate

    gzip compression on incoming and outgoing network traffic or FlatBuffer
  31. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Activate

    gzip compression on incoming and outgoing network traffic or FlatBuffer • Cache data on disk (image, http responses) with reasonable TTL
  32. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Activate

    gzip compression on incoming and outgoing network traffic or FlatBuffer • Cache data on disk (image, http responses) with reasonable TTL • Server side cache headers like ETag & Last- Modified
  33. Hasan Hosgel #DroidConTN Possible improvements CPU Memory I/O • Activate

    gzip compression on incoming and outgoing network traffic or FlatBuffer • Cache data on disk (image, http responses) with reasonable TTL • Server side cache headers like ETag & Last- Modified • Use JobScheduler API to batch across system or better use push notifications for update information
  34. Hasan Hosgel #DroidConTN Optimizing ArrayList public List<String> getDcTnNames(List<Attendee> attendees) {

    List<String> names = new ArrayList<>(); for (Attendee attendee : attendees) { names.add(attendee.name); } return names; } JAVA
  35. Hasan Hosgel #DroidConTN Optimizing ArrayList public List<String> getDcTnNames(List<Attendee> attendees) {

    List<String> names = new ArrayList<>(attendees.size()); for (Attendee attendee : attendees) { names.add(attendee.name); } return names; } JAVA
  36. Hasan Hosgel #DroidConTN Optimizing ArrayList @Override public boolean add(E object)

    { Object[] a = array; int s = size; if (s == a.length) { Object[] newArray = new Object[s + (s < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : s >> 1)]; System.arraycopy(a, 0, newArray, 0, s); array = a = newArray; } a[s] = object; size = s + 1; modCount++; return true; } JAVA
  37. Hasan Hosgel #DroidConTN Optimizing ArrayList void addDcTnSpeaker(ArrayList<String> attendees, List<String> speakers)

    { attendees.ensureCapacity(attendees.size() + speakers.size()); for (String speaker : speakers) { attendees.add(speaker); } } JAVA
  38. Hasan Hosgel #DroidConTN Optimizing Bundle public static DcTnScheduleFragment instance(int startMode)

    { final DcTnScheduleFragment fragment = new DcTnScheduleFragment(); final Bundle bundle = new Bundle(); bundle.putInt(START_MODE, startMode); fragment.setArguments(bundle); return fragment; } JAVA
  39. Hasan Hosgel #DroidConTN Optimizing Bundle public static DcTnScheduleFragment instance(int startMode)

    { final DcTnScheduleFragment fragment = new DcTnScheduleFragment(); final Bundle bundle = new Bundle(1); bundle.putInt(START_MODE, startMode); fragment.setArguments(bundle); return fragment; } JAVA
  40. Hasan Hosgel #DroidConTN Optimizing StringBuilder public StringBuilder getDcTnNames(List<String> names) {

    StringBuilder builder = new StringBuilder(); for (String name : names) { if (builder.length() > 0) { builder.append(", "); } builder.append(name); } return builder; } JAVA
  41. Hasan Hosgel #DroidConTN Optimizing StringBuilder public StringBuilder getDcTnNames(List<String> names) {

    StringBuilder builder = new StringBuilder(names.size() * 13); for (String name : names) { if (builder.length() > 0) { builder.append(", "); } builder.append(name); } return builder; } JAVA
  42. Hasan Hosgel #DroidConTN Optimizing StringBuilder final void append0(char[] chars) {

    int newCount = count + chars.length; if (newCount > value.length) { enlargeBuffer(newCount); } System.arraycopy(chars, 0, value, count, chars.length); count = newCount; } JAVA
  43. Hasan Hosgel #DroidConTN Optimizing StringBuilder public StringBuilder addDcTnOrganizer(StringBuilder names, List<String>

    organizers) { names.ensureCapacity(names.length() + organizers.size() * 13); for (String organizer : organizers) { if (names.length() > 0) { names.append(", "); } names.append(organizer); } } JAVA
  44. Hasan Hosgel #DroidConTN Optimizing Moar – The Loop public StringBuilder

    addDcTnOrganizer(StringBuilder names, List<String> organizers) { names.ensureCapacity(names.length() + organizers.size() * 13); for (String organizer : organizers) { if (names.length() > 0) { names.append(", "); } names.append(organizer); } } JAVA
  45. Hasan Hosgel #DroidConTN Optimizing Moar – The Loop public StringBuilder

    addDcTnOrganizer(StringBuilder names, List<String> organizers) { names.ensureCapacity(names.length() + organizers.size() * 13); for (int i = 0; i < organizers.size(); i++) { String organizer = organizers.get(i); if (names.length() > 0) { names.append(", "); } names.append(organizer); } } JAVA
  46. Hasan Hosgel #DroidConTN Optimizing Moar – The Loop public StringBuilder

    addDcTnOrganizer(StringBuilder names, List<String> organizers) { names.ensureCapacity(names.length() + organizers.size() * 13); for (int i = 0, organizersSize = organizers.size(); i < organizersSize; i++) { String organizer = organizers.get(i); if (names.length() > 0) { names.append(", "); } names.append(organizer); } } JAVA
  47. Hasan Hosgel #DroidConTN Optimizing Moar – The Loop public StringBuilder

    addDcTnOrganizer(StringBuilder names, List<String> organizers) { final int size = organizers.size(); names.ensureCapacity(names.length() + size * 13); for (int i = 0; i < size; i++) { String organizer = organizers.get(i); if (names.length() > 0) { names.append(", "); } names.append(organizer); } } JAVA
  48. Hasan Hosgel #DroidConTN Optimizing Much Moar – Method Invocation public

    void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); text.setTextColor(attendee.isOrganizer() ? getResources().getColor(R.color.accent) : getResources().getColor(R.color.black)); avatar.setImageResource(attendee.getAvatar()); welcomeText.setText(getString( R.string.hello_world, attendee.name)); } JAVA
  49. Hasan Hosgel #DroidConTN Optimizing Much Moar – Method Invocation public

    void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); final Resources res = getResources(); text.setTextColor(attendee.isOrganizer() ? res.getColor(R.color.accent) : res.getColor(R.color.black)); avatar.setImageResource(attendee.getAvatar()); welcomeText.setText(getString( R.string.hello_world, attendee.name)); } JAVA
  50. Hasan Hosgel #DroidConTN Optimizing Much Moar – Method Invocation public

    void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); final Resources res = getResources(); text.setTextColor(attendee.isOrganizer() ? res.getColor(R.color.accent) : res.getColor(R.color.black)); avatar.setImageResource(attendee.getAvatar()); welcomeText.setText(res.getString( R.string.hello_world, attendee.name)); } JAVA
  51. Hasan Hosgel #DroidConTN Optimizing Access Methods private Attendee attendee; public

    void onViewCreated(View view, Bundle savedInstanceState) { button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { makeText(getContext(), getWelcomeTextFor(attendee.getName()), LENGTH_SHORT).show(); } }); } private String getWelcomeTextFor(String name) { return getResources().getString(R.string.welcome_text, name); } JAVA
  52. Hasan Hosgel #DroidConTN Finding Access Methods https://github.com/JakeWharton/dex-method-list $ ./build/dex-method-list src/test/resources/one.apk

    … package.DcTnScheduleFragment access$000(DcTnScheduleFragment ) package.DcTnScheduleFragment access$100(DcTnScheduleFragment , String) … CL
  53. Hasan Hosgel #DroidConTN Optimizing Access Methods Attendee attendee; public void

    onViewCreated(View view, Bundle savedInstanceState) { button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { makeText(getContext(), getWelcomeTextFor(attendee.getName()), LENGTH_SHORT).show(); } }); } String getWelcomeTextFor(String name) { return getResources().getString(R.string.welcome_text, name); } JAVA
  54. Hasan Hosgel #DroidConTN Sources • https://ssl.www8.hp.com/ww/en/secure/pdf/4aa5-7696enw.pdf • http://www.mobilejoomla.com/media/press/responsive-vs-serverside/Responsive- Design-vs-Server-Side-Solutions-Infographic.jpg •

    https://speakerdeck.com/jakewharton/eliminating-code-overhead-square-hq-2015 • http://periplanisi.com/android/2013/11/multi-pass-viewgroup-and-performance/ • https://slideshare.net/dougsillars/android-app-performance-europe-2015 • https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE