Search articles by title

Filter articles by category

This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
Showing 0 results
of 0 items.
highlight
Reset
Engineering

OOM - Bitmap resource analysis

10
min. read

For every OOM you get in your app, mostly it’s because there are large Bitmaps created and kept inside memory at Runtime.

Android Studio provides a handful tool, Profiler, which you can use for recording and browsing memory usage and easily find all the references that been kept.

1 — Know your memory

If you use the tool on devices with different OS versions, you will see the columns of the results have one different like below:

on Android 6
on Android 8

It’s clear to see one more column call Native Size will be used on Android 8. This is because Google has changed the way to store the pixel data of a Bitmap, which you can check the official document for more detail. To be short, the difference is:

  • Pre 8: store pixel data in Java Heap
  • Post 8: store pixel data in Native Heap

So even the pixel data size of Bitmap are both shown in Retained Size, they are stored in different places based on the OS version.

2 — Identify target Bitmap

The way to store a Bitmap will affect whether we can preview a Bitmap or not. If we profile on devices before 8, we can see the reference image like below:

This is pretty useful when you are just starting to find out what image the Bitmap is.

3 — What should we take more focus on

When you start analyzing the Bitmap memory, you may see situation like this:

An incredibly large Bitmap exists at Runtime, consuming nearly 8.3MB of memory. It’s quite wasting since the Java heap on low-end devices may only have 16~32MB. This kind of Bitmap will put a lot of pressure on memory and cause GC constantly.

After looking into it, it turns out it’s a square image that we use to show the placeholder. And if you do some math on the number, you will find out the size of the image is:

// Since Android will load an image with flag ARGB_8888, we will need 4byte  // to represent the color of a pixel. 8294471 ≈ 1440 x 1440 x 4

Potential way out

Except using 3rd party library or tools to shrink image size before importing. Android also provides ways to deal with big image:

  • Enable cruncherEnabled, so the AAPT will shrink the images at compile time.
  • Use WebP instead of PNG, JPG.
  • Use VectorDrawable for graphic icons or symbols.

For more details, you can check the official document.

None of these is a silver bullet to solve the memory issue of Bitmap, because:

  • cruncherEnabled and WebP can only help to shrink the APK size. The Image will still turn into an enormous Bitmap if the original size is big. If you are curious about why WebP doesn’t help, please check OutOfMemoryError — WebP.
  • VectorDrawable is only fully supported by the system with the OS version is above 21(Lollipop). The support library can help to support down to 7(Eclair), but instead of using VectorDrawable, it will become VectorDrawableCompat.

How we gonna do

In the end, we choose to use VectorDrawable with the following reason:

  • We’ve already turned to use WebP to shrink APK size, there’s no reason to use PNG again.
  • Most use cases in the project are easy to replace with VectorDrawable.

What we have to do is:

  • Add the vectorDrawables.useSupportLibrary = true in defaultConfig.
  • Replace android:src with app:srcCompat in xml.
  • setImageResource can be kept.

After replacing with VectorDrawable, the size of the largest Bitmap at Runtime will become only 600K:

And 2KB in VectorDrawableComapt on pre 21:

What’s more

Caveat

Even VectorDrawable seems powerful, you should use it wisely because:

  • VectorDrawable works like drawing graph at Runtime, the calculation and drawing commands must have a performance impact.
  • On pre 21. The system will cache VectorDrawableCompat by size, which means if you apply an individual VectorDrawableCompat into Views with different sizes, it will need to recreate and redraw every time. Check official document for more detail.
  • Enable setCompatVectorFromResourcesEnabled(boolean) to have support on original settings of ImageView or TextView should be careful about OOM issue.

As I said, none of the solutions is a silver bullet, choose a suitable solution based on the use case. And always remember: “Perf matters”.

Useful command

With devices pre 21, you can’t use Profile to check the memory usage. Instead, you have to dump the heap manually:

  • Find PID

adb shell ps | grep "<package name>"

  • Pull the heap file

adb shell am dumpheap <pid> /data/local/tmp/android.hprof

  • Dump the heap

adb pull /data/local/tmp/android.hprof

Engineering

Understanding Grindr's WebP Image Format: Benefits, OOM Errors, and Memory Management in Android

5
min. read

WebP is an image format which is both lossy and lossless compression. Widely use in all Android app, including us. If you wish to get more detail about WebP, please check the following link:

Why WebP

We use WebP heavily inside the project not just because it save the network bandwidth but also cut down size for all image resources to save APK size.

But if you don’t pay attention to the bitmap size that it will become at Runtime, you may go into OOM error like us.

How does it happen

Stacktrace

When we look at the crash log, it will start from the inflating process:

and end up calling to getDrawable, which cause the system to allocate a bitmap for pixel data:

Suspect Image

Let’s take a look at the size again. Because the system will use ARGB_8888 to create a bitmap by default, we can divide the number by 4:

3688412 / 4 = 921603 = 960 * 960

The result shows the image size is 960. Luckily, there's only one ImageView inside the XML file, so we quickly identify the image which causes OOM error.

Targeting image resource

Since the screenDensity of the crashed device is 320. We found the image inside drawable-xhdpi:

It’s a WebP with the size just the same as we expect, now we find the reason for the OOM.

Lesson learn

WebP can be pretty small in size but may be very large in bitmap at Runtime. The bitmap size of a WebP will depend on the size of the image before the transformation. Don’t create a WebP from a PNG that the size is larger than you need.

What’s more

If we look at the distribution on all OS version, you can see the crash more likely happens on OS version from 3 to 7:

The reason for this is because Google has changed the location to store bitmap.

  • Version 3 to 7: a bitmap will be stored inside the Dalvik heap, which is limited and mostly is very small.
  • Version 8+: a bitmap will be placed inside the Native heap, which is expandable with a larger limit, sometimes the limit depends on the physical memory size.

With the difference above, you will more easily get OOM on Android 3 to 7, to check more detail about it, please refer to the official document:

If you curious about how this gonna influence the Bitmap Memory, please check:

Company Updates

Introducing the World’s First Interactive Cum Calculator

Because in 2025, every bite counts—yes, even loads.
4
min. read

Dear Grindr Community,

At Grindr, we’re all about connection—whether it’s a spark, a scroll, or something a little more… hands-on. But in a world obsessed with optimizing every aspect of life—from your sleep score to your gut microbiome—there’s one nutrient-rich resource that’s been scandalously overlooked. That’s right, we’re talking about cum.

Today, we’re hosting the world’s first Nutritional Load Label¹— a Grindr Blog exclusive that finally puts the vitamins, minerals, and precious protein of your favorite milk substitute under the microscope. Forget potatoes, protein bars, and kale smoothies. 2025 demands more. It’s time to log your daily intake of the world’s most unexpected nutrient source.

How to Use the Load Label

  1. View the Load Label below.
  2. Enter the Number of Loads you want to calculate.
  3. View Your Results, which will show an approximate nutritional breakdown (calories, protein, etc.).
Interactive Nutrition Label (Semen Averages)
Nutrition Facts
Serving Size:
Calories
Calories from Fat
Total Fat
Cholesterol
Sodium
Total Carbohydrate
- Sugars (Fructose)
Protein
Zinc
Calcium
Magnesium
Potassium
Vitamin C
Vitamin B12
Citric Acid
Lactic Acid
Not a significant source of Dietary Fiber, Vitamin D, Iron, or many other nutrients.
*Percent Daily Values (%DV) are based on a 2,000 calorie diet.
Caloric content: per load.

That’s all there is to it—no extra steps or details needed. Show your friends. Show your family. Show the world.

Naturally, these figures aren’t carved in stone—hydration, diet, and cosmic forces of testicular load all play a role. But we’ve compiled enough data through our research in order to give you a good idea.

Disclaimer: While the ingredients in a load are generally safe, ingesting it is not FDA-approved for nutritional purposes. But hey, before you get too adventurous, remember: practice safe sex and get tested regularly. Stay safe and savvy, babe.

Can Your Diet Handle Loads? A Checklist

Vegan — Some folks say if it’s from any animal, it’s a hard no. Others claim if it’s a consenting human, it’s basically cruelty-free—you decide, because the last thing we want to do is mess with a vegan.

Keto — Remember, every carb counts, but if you can pencil it into your 25-gram limit, you can consider it part of your daily bread (or just count is as electrolytes and move on).

Paleo — Our ancestors didn’t count macros—they just rawdogged life, ate whatever they could catch, and died at 30. If unprocessed, ancestral simplicity is your vibe, consider this the OG protein source. Farm-to-table? Back then, it was cave-to-mouth. Drink up.

Intermittent Fasting — No protein can go in your mouth before 12pm. But after that, go ahead, girl, get your fill.

Carnivore — Beat your meat and eat it too. With fruits and veggies off the table, a consenting partner’s contribution might be the only variety you’ve got left.

More Disclaimers

  1. Not an Endorsement: We’re not telling you to replace breakfast, second breakfast, or even midnight snacks with, well, cum. Any medical professional would likely yell at us.
  2. Social Repercussions: Whipping out the Interactive Load Label during a conversation about local produce might send your dinner guests scurrying. Use responsibly.
  3. Evolving Science: Like any frontier, the data will evolve as more daring souls look deeper. To that we say: we’re on it. So don’t be surprised if next year’s iteration includes charts on pH levels and differing flavor profiles.
Because in 2025, every bite counts—yes, even loads.
No results found.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.