1.2K Followers
199 Following
1,086 Posts
Android Eng @Square | LeakCanary, Curtains, Radiography, square/logcat, square/PAPA. He/Him.
Technical Bloghttps://hashnode.com/@py
Insta (blading, baking & family)https://instagram.com/py.ricau
Android sourceshttps://androidsrc.dev

[French]

Mardi 21 Octobre (dans deux semaines!) à 19h, le Paris Android User Group organise un meetup chez Radio France. Il paraît que le lieu est magnifique!

Je serai là en 2e partie pour vous parler de benchmarks dignes de confiance.

https://www.meetup.com/android-paris/events/311419349/

#AndroidDev #paris

Just created a group of Android Perf volunteers at work that are making themselves available for teaching, mobbing, etc.. and really happy that we've found a great name for it:

Android Performance EXperts, aka APEX

#AndroidDev

What do you all think of these definitions I just added?

Now, this TreeMap looks cool. For a second it felt really awesome.

Until I started trying to use it. The giant blocks are a few big arrays, not terribly interesting. Note that I'm only displaying the first level of depth here, so every rectangle we see is a root node. All these tiny rectangles are dominated by root.

I saw views and activities being dominated by root, when I really expected them to be a part of a parent rectangle that'd be a large block in the chart.

That's weird!

So, I plugged my heap dump parser (Shark) into the Dominator tree code from perflib (source: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:perflib/src/main/java/com/android/tools/perflib/heap/analysis/LinkEvalDominators.kt;l=36;drc=499fa43009666c0f0a686d8e21722dbea8b2ecf0)

Then I output the dominator tree as a CSV file, imported it into Google Spreadsheet, selected the 3 columns (dominated, dominator, size) and inserted a TreeMap chart.

Here's the result

LeakCanary now does incorrectly show 3 objects leaks / 40 bytes, when it should be 2 objects (Everything + Universe) and 28 bytes.

YourKit is also correct in its dominator computation.

So, at this point, I've confirmed again & again that LeakCanary's approach is broken, and now I need to figure out a fix.. Unfortunately, a quick search shows standard dominators is expensive to compute (simple algo is quadratic!).

Ok, trying again with a dedicated Answer class this time, no more string interning
I double checked, and it turns out I picked a bad example. The string "42" was unfortunately already references by a GC root, because it's a static constant in... RoomMasterTable.defaultId 🤣
YourKit also has the same dominator logic (retained size for Everything is shallow self + shallow size of Universe), but interestingly it computes comes up with different totals. I suspect it's account for padding for byte alignment, where a 12 byte shallow size becomes 16 bytes? Not certain.

Much to my surprise, LeakCanary is computing the correct result this time: "Everything" only retains but not "Universe", nor the answer "42". That's not what I was getting with my unit test, so I need to figure out what's different.

References are still 4 bytes here, but on an Android VM every instance has an additional shadow$_klass_ ref field and a shadow$_monitor_ int field.

Android Studio and LeakCanary seem in sync on retained size.