Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Optimizing the Netflix Android application

"Optimizing the Netflix Android application". These slides were used at the Mobile Event hosted by Netflix on 4/21/2016.

  • Login to see the comments

Optimizing the Netflix Android application

  1. 1. Optimizing the Netflix Android Application 1 Francois Goldfain Engineering Manager
  2. 2. Images 2
  3. 3. Minimize Image Resolution ! Request different images based on screen resolution, screen density and device memory" ! Trade-off between quality and performance" ! Storing different image sizes on your server is worth it" ! Re-consider your logic and thresholds regularly" 3 86 x 120 6KB to download 20KB in heap (Kindle Fire 2011, RCA Tablet 2014) 150 x 210 10KB to download 61KB in heap (Amazon Fire Tablet 2015) 197 x 276 13KB to download 106KB in heap (Nexus 7 Tablet 2013)
  4. 4. Leverage WebP format ! Compressed image size decreased by at least 30% with no visible quality difference" ! Support for alpha & animation makes it a one-stop image format" ! Supported natively since Android 4.0" ! Software library available for earlier Android versions and for iOS" ! Limited browser support" 4 Image Resolution: 592 x 333 File size in JPEG format: 39KB File size in WebP: 22KB 56% reduction!
  5. 5. Image Disk Caching ! By default, HTTP responses are not cached" ! android.net.HttpResponseCache turns on caching for all http requests (based on Cache-Control)" ! Application-level disk caching allows for greater flexibility" ! Netflix Disk Cache based on Volley" ○ Max size varies with device disk space: Between 5MB and 25MB" ○ Store cache files under Context.getCacheDir() " ○ Least-Recently-Used (LRU) for images, App Session life cycle for other short lived assets" ○ Ignore hostname part of URL for images: " http://cdn3.nflximg.net/ipl/13071/d2b1ce2100319d06e5e7dec5423b0e72839b8479.webp 5
  6. 6. Bitmap Heap Caching ! Decoding an image from the disk is CPU intensive" ! In-memory L1 Bitmap cache needed for smooth scrolling and efficiency" ! BitmapLruCache based on android.util.LruCache" ○ HashMap that returns Bitmap object" ○ Evict least-recently-used Bitmap when full " ! Decoded Bitmaps in heap much larger than when compressed on disk " ! Large Bitmap cache when dealing with lots of images" ○ 50% of Runtime.maxMemory() with android:largeHeap="true" ○ Empty cache when application is in background with Application.onTrimMemory() " 6
  7. 7. Use RGB 565 when possible ! By default, images are decoded with Bitmap.Config.ARGB_8888 for optimal quality" ○ Alpha channel only pertains to translucent images" ○ Additional colors not necessary in many cases" ! Consider using RGB_565 whenever possible" ○ Faster decoding" ○ Only 2 bytes of heap per pixel, instead of 4" " 7 BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); decodeOptions.inPreferredConfig = Bitmap.Config.RGB_565; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); " RGB 565 337x599 394KB heap ARGB 8888 337x599 788KB heap "
  8. 8. RGB 565 Not Always Right Choice 8 Accentuated color banding with RGB 565
  9. 9. Data Requests 9
  10. 10. Cost Of Cellular Connection ! Networking biggest battery hog" ! Minimize radio time to avoid battery drain" ! Understand high cost of sending/receiving data" ○ Wake-up and initialize modem" ○ Open TCP connection" ○ Send/receive data at full cellular power" ○ Radio powered for another ~30 seconds after last request is complete" ! Worst scenario when each data request triggers full cycle 10
  11. 11. Batch Network Requests ! Accumulate data requests in a queue and send them all together" ! Pre-fetch all data that user might need in the short term" ! Piggyback on other network operations to trigger your data requests" (JobScheduler) 11
  12. 12. Batch Network Requests (2) 12 " https://www.youtube.com/watch?v=7sKC2JBc4dY"
  13. 13. Batch Network Requests (3) 13 Load Home Screen with No Prefetch request Load Home Screen with Prefetch requests Prefetch Requests Subsequent user inputs do not trigger additional data requests Each subsequent user input do trigger additional data request
  14. 14. Avoid Polling ! Cause of continuous waste of bandwidth and energy" ! Unnecessary load on server for nothing" ! Leverage Google Cloud Messaging to trigger a refresh 14
  15. 15. Avoid Polling (2) 15 https://www.youtube.com/watch?v=7TXIqa6Ny7Y"
  16. 16. Prioritize Data Requests ! Assign different priorities to data requests stored in the queue" ! Consider different queues for data and asset files (images…)" ! Cancel/stop data requests at critical times 16 HIGH_PRIORITY LOW_PRIORITY
  17. 17. Prioritize Data Requests ! Assign different priorities to data requests stored in the queue" ! Consider different queues for data and asset files (images…)" ! Cancel/stop data requests at critical times 16 https://youtu.be/7IkILwruZLY
  18. 18. Adopt Efficient Response Format ! Prefer binary serialization format (protobuf, flatbuffers…)" " ! If using chatty format (XML, JSON), optimize parsing (no reflection). 17
  19. 19. Use Few Persistent TCP Connections ! Cellular network performance degrades with the number of open TCP connections" ○ Same bandwidth shared among more TCP connections" ○ Limited throughput and increased latency" ○ Energy wasted maintaining TCP connections" 18 ! Solution: Use few persistent TCP connections" ○ Limit number of different server endpoints" ○ HTTP Pipelining with HTTP 2" ○ Connection Pooling with HTTP 1.1 " ! Bonus: Adjust the number of TCP connections with network type
  20. 20. Terminate TCP Connections ! HttpUrlConnection keeps TCP connection open after request (“Keep-Alive”)" ! TCP connection closed late causes further battery drain" ! Trade off between reusing connections and closing them promptly to reduce energy drain 19 HttpURLConnection closeconn = (HttpURLConnection) url.openConnection(); closeconn.setRequestProperty("connection", "close"); "
  21. 21. CPU Thrashing 20
  22. 22. CPU Power States ● Busy loop prevents power management from moving CPU to low power state ● Device power management adjusts chipset power level depending on needs 21 private class VideoThread(){ public void run(){ while(playbackRunnning) { idx = mMediaCodec.dequeueInputBuffer(timeOutUs); //wait 5ms if (idx >= 0) { ...//fill input buffer mMediaCodec.queueInputBuffer(idx,…); } idx = mMediaCodec.dequeueOutputBuffer(..., timeOutUs); //wait 5ms ...//pass output buffer to renderer } } }
  23. 23. CPU Power States 22 private class VideoInputThread(){ public void run(){ while (playbackRunning){ idx = mMediaCodec.dequeueInputBuffer(-1); //wait till buffer is available ... //fill input buffer mMediaCodec.queueInputBuffer(idx,...); } } } private class VideoOutputThread(){ public void run(){ while (playbackRunning){ idx = mMediaCodec.dequeueOutputBuffer(-1); //wait till buffer is available .... //pass output buffer to renderer } } } ● Blocking on decoder allows power management to move CPU to low power state
  24. 24. Sharing large buffer between C++ & Java ! Passing large C++ buffer to Java byte[] involves copying data" ! Consider using a direct ByteBuffer instead of byte[] when data is large 23 static jbyteArray VectorToJavaByteArray(JNIEnv* env, std::vector<unsigned char> v) { int32_t size = v.size(); unsigned char * arr = v.data(); // allocate a new Java byte[] and copy the content of c++ buffer jbyteArray jbyteArray = env->NewByteArray(size); env->SetByteArrayRegion(jbyteArray, 0, size, (const jbyte*) arr); return jbyteArray; } " static jobject VectorToJavaByteBuffer(JNIEnv* env, std::vector<unsigned char> v) { int32_t size = v.size(); unsigned char * arr = v.data(); // create a reference to Java ByteBuffer object that holds a pointer to the c++ buffer jobject buffer = env->NewDirectByteBuffer(arr, size); return buffer; }
  25. 25. Conclusion ! Learn about mobile performance patterns" " ! Profile how your application uses resources" " ! Understand how technical decisions impact performance" " ! Balance trade-offs 24
  26. 26. References ! Google’s Android Performance Patterns videos" https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE" " ! AT&T’s best practices" https://developer.att.com/application-resource-optimizer/docs/best-practices)" " ! Profiling Tools" ○ Android Studio’s Network Traffic Tool" ○ AT&T ARO (Application Resource Optimizer)" ○ Charles Proxy" 25
  27. 27. Q & A 26

×