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

Talking Trash: The Evolution of Garbage Collect...

Romain Guy
October 27, 2018

Talking Trash: The Evolution of Garbage Collection on Android

Learn how the Android garbage collector has evolved from Dalvik to ART. This talk explains why you should worry more about good code than avoiding allocations.

Romain Guy

October 27, 2018
Tweet

More Decks by Romain Guy

Other Decks in Programming

Transcript

  1. Optimized for size 
 | 
 +- JIT optimizations not

    
 | as powerful 
 | 
 +- Allocation/collection slow 
 | 
 +- Heap fragmentation Dalvik
  2. So: _ Avoid allocation whenever possible > For example: enums

    _ Primitive types are cool 
 (autoboxing is not)
  3. ART Optimized for performance JIT + AOT Faster allocation/collection Heap

    defragmentation Large object heap So: Allocate as necessary (yes, even enums) Use appropriate types But: phones are still constrained batteries are, too be aware of inner-loop bottlenecks
  4. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  5. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Leak! C++
  6. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  7. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  8. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Crash! C++
  9. Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Crash! C++ (maybe)
  10. Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! Java // eventually freed
  11. Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! Java // eventually freed // code using thing…
  12. Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! No crash! Java // eventually freed // code using thing…
  13. Runtime GC Concerns How long does allocation take? 
 How

    long does collection take? What impact does this have across all threads?
  14. Runtime GC Concerns How long does allocation take? 
 How

    long does collection take? What impact does this have across all threads? When do collections happen?
  15. Runtime GC Concerns How long does allocation take? 
 How

    long does collection take? What impact does this have across all threads? When do collections happen? 
 How efficient is heap usage?
  16. Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause)
  17. Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause)
  18. Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause) Collect (concurrent)
  19. D/dalvikvm: GC_FOR_ALLOC freed 2K, 50% free 197613K/392536K, paused 6ms, total

    6ms I/dalvikvm-heap: Forcing collection of SoftReferences for 2000012-byte allocation D/dalvikvm: GC_BEFORE_OOM freed 0K, 50% free 197613K/392536K, paused 6ms, total 6ms E/dalvikvm-heap: Out of memory on a 2000012-byte allocation. Sad Logcat
  20. D/dalvikvm: GC_FOR_ALLOC freed 2K, 50% free 197613K/392536K, paused 6ms, total

    6ms I/dalvikvm-heap: Forcing collection of SoftReferences for 2000012-byte allocation D/dalvikvm: GC_BEFORE_OOM freed 0K, 50% free 197613K/392536K, paused 6ms, total 6ms E/dalvikvm-heap: Out of memory on a 2000012-byte allocation. Sad Logcat
  21. D/dalvikvm: GC_FOR_ALLOC freed 2K, 50% free 197613K/392536K, paused 6ms, total

    6ms I/dalvikvm-heap: Forcing collection of SoftReferences for 2000012-byte allocation D/dalvikvm: GC_BEFORE_OOM freed 0K, 50% free 197613K/392536K, paused 6ms, total 6ms E/dalvikvm-heap: Out of memory on a 2000012-byte allocation. Sad Logcat
  22. D/dalvikvm: GC_FOR_ALLOC freed 2K, 50% free 197613K/392536K, paused 6ms, total

    6ms I/dalvikvm-heap: Forcing collection of SoftReferences for 2000012-byte allocation D/dalvikvm: GC_BEFORE_OOM freed 0K, 50% free 197613K/392536K, paused 6ms, total 6ms E/dalvikvm-heap: Out of memory on a 2000012-byte allocation. Sad Logcat
  23. D/dalvikvm: GC_FOR_ALLOC freed 2K, 50% free 197613K/392536K, paused 6ms, total

    6ms I/dalvikvm-heap: Forcing collection of SoftReferences for 2000012-byte allocation D/dalvikvm: GC_BEFORE_OOM freed 0K, 50% free 197613K/392536K, paused 6ms, total 6ms E/dalvikvm-heap: Out of memory on a 2000012-byte allocation. Sad Logcat
  24. ART Allocation RosAlloc Replacement for dlmalloc Thread-local allocations Grouped small

    allocations, page-aligned large allocations Finer-grained locks
  25. ART Allocation RosAlloc Replacement for dlmalloc Thread-local allocations Grouped small

    allocations, page-aligned large allocations Finer-grained locks 4-5x faster than Dalvik!
  26. ART Allocation RosAlloc Replacement for dlmalloc Thread-local allocations Grouped small

    allocations, page-aligned large allocations Finer-grained locks 4-5x faster than Dalvik!
  27. Dalvik GC Mark root set (pause) Mark reachable I (concurrent)

    Mark reachable II (pause) Collect (concurrent)
  28. ~10ms Dalvik GC Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause) Collect (concurrent)
  29. ~10ms Mark root set (pause) Mark reachable I (concurrent) Mark

    reachable II (pause) Collect (concurrent) ART GC
  30. Mark root set (concurrent) Mark reachable I (concurrent) Mark reachable

    II (pause) Collect (concurrent) ART GC Faster!
  31. ~3ms Mark root set (concurrent) Mark reachable I (concurrent) Mark

    reachable II (pause) Collect (concurrent) ART GC Faster!
  32. ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation
  33. ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation Less heap resizing
  34. ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation Less heap resizing Fewer GC_FOR_ALLOC pauses
  35. ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation Less heap resizing Fewer GC_FOR_ALLOC pauses 
 Faster runtime
  36. ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings
  37. ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings System and Google Play Services
  38. ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings System and Google Play Services Smaller heaps for all
  39. ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings System and Google Play Services Smaller heaps for all
  40. Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  41. Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  42. Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  43. Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  44. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ...
  45. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ...
  46. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  47. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  48. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  49. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  50. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  51. Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  52. ART in O+ Young generation collections gone in O Enabled

    in AOSP Watch for that future release…
  53. Object Pools Conventional wisdom Reusing objects is faster (saves on

    allocation/collection time)
 Actual wisdom
  54. Object Pools Conventional wisdom Reusing objects is faster (saves on

    allocation/collection time)
 Actual wisdom As of Oreo, synchronized object pools are generally slower
  55. Soooo… What Now? Creating garbage is okay (and so is

    collecting it)
 Use the types and objects you need Even enums
 GC is still overhead But not as critical to avoid as it was in Dalvik Make the right choices for your architecture Avoid overhead in critical sections when possible
  56. Jank Test Autoboxing public void run() { long startTime =

    System.currentTimeMillis(); float f = 0f; for (int i = 0; i < mHolder.length; ++i, f += 1.0f) { mHolder[i] = f; } System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); } private Float[] mHolder = new Float[100_000];
  57. Jank Test Autoboxing public void run() { long startTime =

    System.currentTimeMillis(); float f = 0f; for (int i = 0; i < mHolder.length; ++i, f += 1.0f) { mHolder[i] = f; } System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); } private Float[] mHolder = new Float[100_000]; I/System.out: Alloc time = 28 D/dalvikvm: GC_FOR_ALLOC freed 2047K, 1% free 337371K/339492K, paused 10ms, total 10ms I/System.out: Alloc time = 29
  58. Jank Test Autoboxing public void run() { long startTime =

    System.currentTimeMillis(); float f = 0f; for (int i = 0; i < mHolder.length; ++i, f += 1.0f) { mHolder[i] = f; } System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); } private Float[] mHolder = new Float[100_000]; I/System.out: Alloc time = 28 D/dalvikvm: GC_FOR_ALLOC freed 2047K, 1% free 337371K/339492K, paused 10ms, total 10ms I/System.out: Alloc time = 29 I/System.out: Alloc time = 3 I/System.out: Alloc time = 2 I/System.out: Alloc time = 4
  59. Jank Test Bitmaps public void run() { long startTime =

    System.currentTimeMillis(); mBitmap = Bitmap.createBitmap(1_000, 1_000, Bitmap.Config.ARGB_8888); System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); }
  60. Jank Test Bitmaps public void run() { long startTime =

    System.currentTimeMillis(); mBitmap = Bitmap.createBitmap(1_000, 1_000, Bitmap.Config.ARGB_8888); System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); } I/System.out: Alloc time = 16 D/dalvikvm: GC_FOR_ALLOC freed 3907K, 2% free 341280K/347244K, paused 7ms, total 7ms I/dalvikvm-heap: Grow heap (frag case) to 337.165MB for 4000012-byte allocation D/dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 345186K/347244K, paused 7ms, total 7ms
  61. Jank Test Bitmaps public void run() { long startTime =

    System.currentTimeMillis(); mBitmap = Bitmap.createBitmap(1_000, 1_000, Bitmap.Config.ARGB_8888); System.out.println("Alloc time = " + (System.currentTimeMillis() - startTime)); } I/System.out: Alloc time = 16 D/dalvikvm: GC_FOR_ALLOC freed 3907K, 2% free 341280K/347244K, paused 7ms, total 7ms I/dalvikvm-heap: Grow heap (frag case) to 337.165MB for 4000012-byte allocation D/dalvikvm: GC_FOR_ALLOC freed <1K, 1% free 345186K/347244K, paused 7ms, total 7ms I/System.out: Alloc time = 1 I/System.out: Alloc time = 0 I/System.out: Alloc time = 0 I/System.out: Alloc time = 1
  62. data class Float3(x: Float, y: Float, z: Float) fun Tonemap_ACES(x:

    Float3): Float3 { val a = 2.51f val b = 0.03f val c = 2.43f val d = 0.59f val e = 0.14f return (x * (a * x + b)) / (x * (c * x + d) + e) }
  63. inline operator fun Float.plus(v: Float3) = Float3(this + v.x, this

    + v.y, this + v.z) inline operator fun Float.times(v: Float3) = Float3(this * v.x, this * v.y, this * v.z)
  64. 10-23 14:40:04.997 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K,

    paused 4ms, total 4ms 10-23 14:40:05.067 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.147 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.177 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:05.207 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:05.277 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.307 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5125K/5912K, paused 3ms, total 3ms 10-23 14:40:05.357 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 713K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:05.397 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:05.447 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.517 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.607 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.677 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.707 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:05.767 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.837 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.867 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.897 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:05.957 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:05.997 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.037 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.107 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.157 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:06.227 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:06.267 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:06.337 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.367 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.437 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:06.527 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.597 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:06.617 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:06.697 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.717 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.767 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:06.817 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 713K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:06.857 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 711K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:06.937 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:06.957 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.027 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.117 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.157 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.197 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:07.257 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.307 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:07.357 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.397 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 3ms, total 3ms 10-23 14:40:07.447 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.477 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.557 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.617 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.647 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.677 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:07.707 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.727 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:07.767 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.797 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:07.847 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:07.927 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5125K/5912K, paused 5ms, total 5ms 10-23 14:40:08.057 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 713K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:08.077 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:08.107 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:08.147 3885-3908/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:08.207 3885-3901/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms 10-23 14:40:08.267 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 713K, 14% free 5124K/5912K, paused 4ms, total 4ms 10-23 14:40:08.287 3885-3907/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 711K, 14% free 5124K/5912K, paused 5ms, total 5ms 10-23 14:40:08.337 3885-3902/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 4ms, total 4ms
  65. 10-23 14:40:24.847 3885-3909/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K,

    paused 3ms, total 3ms 10-23 14:40:24.917 3885-3903/com.google.ray_trasher D/dalvikvm: GC_FOR_ALLOC freed 712K, 14% free 5124K/5912K, paused 2ms, total 2ms
  66. Core Core Core Core L1 L1 L1 L1 Kryo 385

    (Pixel 3) 4x 32 KiB “Gold” cores
  67. Core Core Core Core L2 L2 L2 L2 L1 L1

    L1 L1 Kryo 385 (Pixel 3) 4x 32 KiB “Gold” cores 4x 256 KiB
  68. Core Core Core Core L2 L2 L2 L2 L3 L1

    L1 L1 L1 Kryo 385 (Pixel 3) 4x 32 KiB “Gold” cores 4x 256 KiB 1x 2 MiB
  69. m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) 64 bytes
  70. m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) RAM 64 bytes
  71. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  72. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  73. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  74. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  75. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  76. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  77. m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) RAM 64 bytes
  78. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  79. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  80. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  81. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  82. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  83. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  84. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  85. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  86. m[0] FloatArray(4) m[1] FloatArray(4) m[2] FloatArray(4) m[n] FloatArray(4) val m

    = ArrayList<FloatArray>(n) for (i in 0 until m.size - 3) { val a = m[i ] val b = m[i + 1] val c = m[i + 2] val d = m[i + 3] computeStuff(a, b, c, d) } L1 64 bytes
  87. 0.0 1.0 2.0 3.0 4.0 5.0 6.0 No thrash L1

    thrash L2 thrash Relative computation times (Pixel 3)