question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Out of memory during trimming memory

See original GitHub issue

Description

We receiving OOM crashes from production app. Their appear while we’re trying to trim memory. Our implementation are the same as described here: https://github.com/facebook/fresco/issues/2136#issuecomment-397608264

Stack trace:

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 280364296 byte allocation with 8388608 free bytes and 197MB until OOM, max allowed footprint 204217504, growth limit 402653184
       at java.util.Arrays.copyOf(Arrays.java:3139)
       at java.util.Arrays.copyOf(Arrays.java:3109)
       at java.util.ArrayList.grow(ArrayList.java:275)
       at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:249)
       at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:241)
       at java.util.ArrayList.add(ArrayList.java:467)
       at com.facebook.imagepipeline.cache.CountingMemoryCache.trimExclusivelyOwnedEntries(CountingMemoryCache.java:411)
       at com.facebook.imagepipeline.cache.CountingMemoryCache.trim(CountingMemoryCache.java:349)
       at com.myapp.utils.FrescoMemoryTrimmableRegistry.trim(FrescoMemoryTrimmableRegistry.java:23)
       at com.myapp.MyApp.onTrimMemory(MyApp.java:200)
       at android.app.ActivityThread.handleTrimMemory(ActivityThread.java:5440)
       at ...

MyApp.java is our Application class with override of onTrimMemory() method in the same way as in comment I posted above. FrescoMemoryTrimmableRegistry.java:

class FrescoMemoryTrimmableRegistry : MemoryTrimmableRegistry {

    private val trimmables = LinkedList<MemoryTrimmable>()

    override fun registerMemoryTrimmable(trimmable: MemoryTrimmable) {
        trimmables.add(trimmable)
    }

    override fun unregisterMemoryTrimmable(trimmable: MemoryTrimmable) {
        trimmables.remove(trimmable)
    }

    @Synchronized
    fun trim(trimType: MemoryTrimType) {
        for (trimmable in trimmables) {
            trimmable.trim(trimType)
        }
    }
}

So crash appear sometimes when app in background (46%) and sometimes when in foreground (54%). According to the message of the crash, system need an insane amount of memory to… trim itself. For example:

Samsung Galaxy J7 Prime (3 GB RAM total): Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 420546432 byte allocation with 8388608 free bytes and 231MB until OOM, max allowed footprint 302209776, growth limit 536870912

Huawei Y7 Prime (2019) (3 GB RAM total): Failed to allocate a 420546432 byte allocation with 8339456 free bytes and 236MB until OOM, max allowed footprint 296859888, growth limit 536870912

HUAWEI Nova 2 Lite (3 GB RAM total): Failed to allocate a 420546432 byte allocation with 25165824 free bytes and 234MB until OOM, max allowed footprint 316307200, growth limit 536870912

Motorola Moto G (5th gen) (2 GB RAM total): Failed to allocate a 280364296 byte allocation with 8388608 free bytes and 197MB until OOM, max allowed footprint 204217504, growth limit 402653184

Motorola Moto E5 Play (1 GB RAM total): Failed to allocate a 186909536 byte allocation with 25149440 free bytes and 125MB until OOM, max allowed footprint 162280960, growth limit 268435456

One more thing I found that as you can see above number of required memory is the same across devices with the same memory: ~178 MB for 1 GB RAM devices, 267 MB for 2 GB RAM devices and 401 MB for 3+ GB RAM devices. Probably it’s coincidence: app attempts to increase the size of the array and due to growth factor it growth with such big steps. And low memory devices give up on step N, 2-GB devices give up on step N+1, and so on.

Reproduction

We’re not able to reproduce this bug on our devices. However it production we have 5% of users who faced with this issue.

Able to reproduce in 100% cases. Please check first comment below for more details.

Additional Information

  • Fresco version: 2.1.0
  • Platform version: Variety of manufactures and Android OS versions. Distribution corresponds to the distribution of platforms for the application as a whole.

Could be related: issues start to occur in our latest app release. We didn’t change anything related to Fresco (like lib version on way of using Fresco API) except adding one more line:

Fresco.getImagePipeline().evictFromMemoryCache(uri)

We call this in very rare cases (for current moment we have only 92 calls of this).

(Not related since I able to reproduce crash without this line)

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
defHLTcommented, Feb 26, 2020

Thanks for the report and investigation. This indeed looks strange. Are you sure there are no huge bitmaps getting cached? Could you please check with Flipper plugin (or by debugging CountingMemoryCache#mCachedEntries) that cached bitmaps are of the reasonable size.

1reaction
GlebMaltsevcommented, Feb 19, 2020

After commenting out onBitmapReady(bitmap) call inside onNewResultImpl() callback crash is gone. It seems that the problem is actually in the wrong work with bitmaps in onBitmapReady(bitmap).

After moving from BaseBitmapDataSubscriber to BaseDataSubscriber problem is gone. I was able to rework logic in my app and now I’m using Closeable References for passing bitmaps across the app.

However, I still have a one last question: how it’s possible that passing single 100 KB Bitmap out from BaseBitmapDataSubscriber.onNewResultImpl(Bitmap) to the app in 100% cases will cause OOM due to attempt of allocating hundreds of megabytes of memory during trimming memory in Fresco cache when user moves app to background and then recover it?

Read more comments on GitHub >

github_iconTop Results From Across the Web

CUDA out of memory error: while allocating the memory #16
Hi I am working on Tesla K40, 12 GB GPU machine. I am facing this error constantly. If I calculate the required memory...
Read more >
Out of memory error when trim XML - java - Stack Overflow
I am doing a program to parse a XML file from http. And the XML have some space at the front of root...
Read more >
Running out of memory - IBM
This problem almost always occurs when the branch & cut tree becomes so large that insufficient memory remains to solve a continuous LP,...
Read more >
Troubleshoot out of memory or low memory issues in SQL ...
Therefore, if SQL Server starts cutting back its memory usage, its memory pool is reduced, and whichever components need memory may not get...
Read more >
Tag: memory trimming - Guy Leech's Blog - WordPress.com
Depending on why you are trimming, this option can be used to only trim when available memory is relatively low although not so...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found