Talking Trash: The Evolution of Garbage Collection on Android

237be48129b762b31847d6167597366d?s=47 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.

237be48129b762b31847d6167597366d?s=128

Romain Guy

October 27, 2018
Tweet

Transcript

  1. 7.

    Optimized for size 
 | 
 +- JIT optimizations not

    
 | as powerful 
 | 
 +- Allocation/collection slow 
 | 
 +- Heap fragmentation Dalvik
  2. 8.

    So: _ Avoid allocation whenever possible > For example: enums

    _ Primitive types are cool 
 (autoboxing is not)
  3. 11.

    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. 18.
  5. 19.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  6. 20.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Leak! C++
  7. 21.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  8. 22.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing C++
  9. 23.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Crash! C++
  10. 24.

    Manual Garbage Collection MyObject* thing = new MyObject; // code

    using thing... delete thing; // code using thing Crash! C++ (maybe)
  11. 26.

    Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! Java // eventually freed
  12. 27.

    Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! Java // eventually freed // code using thing…
  13. 28.

    Automatic Garbage Collection MyObject thing = new MyObject(); // code

    using thing… No leak! No crash! Java // eventually freed // code using thing…
  14. 32.

    Runtime GC Concerns How long does allocation take? 
 How

    long does collection take? What impact does this have across all threads?
  15. 33.

    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?
  16. 34.

    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?
  17. 43.

    Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause)
  18. 44.

    Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause)
  19. 45.

    Dalvik GC Collection Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause) Collect (concurrent)
  20. 65.

    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. 66.

    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. 67.

    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. 68.

    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. 69.

    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
  25. 76.

    ART Allocation RosAlloc Replacement for dlmalloc Thread-local allocations Grouped small

    allocations, page-aligned large allocations Finer-grained locks
  26. 77.

    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. 78.

    ART Allocation RosAlloc Replacement for dlmalloc Thread-local allocations Grouped small

    allocations, page-aligned large allocations Finer-grained locks 4-5x faster than Dalvik!
  28. 97.

    Dalvik GC Mark root set (pause) Mark reachable I (concurrent)

    Mark reachable II (pause) Collect (concurrent)
  29. 98.

    ~10ms Dalvik GC Mark root set (pause) Mark reachable I

    (concurrent) Mark reachable II (pause) Collect (concurrent)
  30. 99.

    ~10ms Mark root set (pause) Mark reachable I (concurrent) Mark

    reachable II (pause) Collect (concurrent) ART GC
  31. 100.
  32. 102.

    Mark root set (concurrent) Mark reachable I (concurrent) Mark reachable

    II (pause) Collect (concurrent) ART GC Faster!
  33. 103.

    ~3ms Mark root set (concurrent) Mark reachable I (concurrent) Mark

    reachable II (pause) Collect (concurrent) ART GC Faster!
  34. 108.
  35. 109.

    ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation
  36. 110.

    ART Collection Minor GC Fast collection of “young generation” Temporary

    objects less expensive 
 Large object heap Less fragmentation Less heap resizing
  37. 111.

    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
  38. 112.

    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
  39. 119.
  40. 125.

    ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings
  41. 126.

    ART in Oreo Concurrent heap compaction Defragmentation in foreground! Less

    heap resizing, GC_FOR_ALLOC Device-wide memory savings System and Google Play Services
  42. 127.

    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
  43. 128.

    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
  44. 130.

    Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  45. 131.

    Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  46. 132.

    Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  47. 133.

    Concurrent Compaction Heap ... T0 Region T1 Region T2 Region

    T3 Region Tn Region ... ... Compaction Phase
  48. 134.
  49. 135.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ...
  50. 136.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ...
  51. 137.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  52. 138.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  53. 139.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  54. 140.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  55. 141.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  56. 142.

    Concurrent Compaction — Allocation Heap ... T0 Region T1 Region

    T2 Region T3 Region Tn Region All-thread Heap ... ... T1 Region Free Pointer
  57. 144.
  58. 147.

    ART in O+ Young generation collections gone in O Enabled

    in AOSP Watch for that future release…
  59. 151.

    Object Pools Conventional wisdom Reusing objects is faster (saves on

    allocation/collection time)
 Actual wisdom
  60. 152.

    Object Pools Conventional wisdom Reusing objects is faster (saves on

    allocation/collection time)
 Actual wisdom As of Oreo, synchronized object pools are generally slower
  61. 153.

    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
  62. 156.

    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];
  63. 157.

    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
  64. 158.

    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
  65. 160.

    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)); }
  66. 161.

    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
  67. 162.

    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
  68. 163.
  69. 164.

    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) }
  70. 165.

    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)
  71. 166.
  72. 167.
  73. 168.
  74. 171.

    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
  75. 172.

    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
  76. 173.
  77. 176.

    Core Core Core Core L1 L1 L1 L1 Kryo 385

    (Pixel 3) 4x 32 KiB “Gold” cores
  78. 177.

    Core Core Core Core L2 L2 L2 L2 L1 L1

    L1 L1 Kryo 385 (Pixel 3) 4x 32 KiB “Gold” cores 4x 256 KiB
  79. 178.

    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
  80. 184.
  81. 186.

    m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) 64 bytes
  82. 187.

    m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) RAM 64 bytes
  83. 188.

    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. 189.

    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. 190.

    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. 191.

    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. 192.

    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
  88. 193.

    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
  89. 194.

    m[0] = FloatArray(4) m[1] = FloatArray(4) m[2] = FloatArray(4) m[n]

    = FloatArray(4) val m = ArrayList<FloatArray>(n) RAM 64 bytes
  90. 195.

    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
  91. 196.

    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
  92. 197.

    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
  93. 198.

    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
  94. 199.

    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
  95. 200.

    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
  96. 201.

    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
  97. 202.

    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
  98. 203.

    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
  99. 204.

    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)
  100. 207.