【问题标题】:Android garbage collection run amokAndroid垃圾收集运行异常
【发布时间】:2012-04-21 00:28:07
【问题描述】:

我在 Activity 中有以下代码。最终,我正在尝试制作帧动画,但 GC 正在扼杀性能。我已经尝试过显式回收,但没有任何区别。

我也知道我可以使用 BitmapFactor.Options.inBitmap 重复使用位图,这确实解决了问题,但将我限制为 API >= 11,这不是一个选项。

此代码仅说明了问题。它不是我的应用程序的一部分:

        Log.d("GC_badness", "0: " + SystemClock.uptimeMillis());
        Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "1: " + SystemClock.uptimeMillis());
        image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "2: " + SystemClock.uptimeMillis());
        image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "3: " + SystemClock.uptimeMillis());
        image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "4: " + SystemClock.uptimeMillis());
        image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "5: " + SystemClock.uptimeMillis());
        image = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
        Log.d("GC_badness", "6: " + SystemClock.uptimeMillis());

这会产生以下日志条目。从 jpg 资源加载的每个位图都会导致至少 3 次垃圾收集,最多 8 次。大多数情况下,它们什么也不收集或几乎什么也不收集。堆没有增长,即使有多条消息说它是。这也很令人困惑。

我被难住了。我找不到重用我的位图 pre-API 11 的方法,而且我无法忍受所有这些无用的垃圾收集带来的巨大延迟。

04-07 18:17:51.860: D/GC_badness(7510): 0: 360583998
04-07 18:17:51.900: D/dalvikvm(7510): GC_FOR_ALLOC freed 34K, 5% free 6320K/6595K, paused 32ms
04-07 18:17:51.900: I/dalvikvm-heap(7510): Grow heap (frag case) to 7.744MB for 1584016-byte allocation
04-07 18:17:51.950: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 5% free 7867K/8199K, paused 27ms
04-07 18:17:52.000: D/dalvikvm(7510): GC_CONCURRENT freed <1K, 5% free 7868K/8199K, paused 2ms+3ms
04-07 18:17:52.030: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 5% free 7868K/8199K, paused 31ms
04-07 18:17:52.030: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 704016-byte allocation
04-07 18:17:52.070: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 4% free 8555K/8903K, paused 37ms
04-07 18:17:52.070: D/dalvikvm(8107): GC_FOR_ALLOC freed 1464K, 39% free 17183K/27911K, paused 62ms
04-07 18:17:52.100: D/GC_badness(7510): 1: 360584238
04-07 18:17:52.100: D/dalvikvm(8189): GC_CONCURRENT freed 286K, 8% free 6917K/7495K, paused 17ms+3ms
04-07 18:17:52.110: D/dalvikvm(7510): GC_CONCURRENT freed 1546K, 22% free 7009K/8903K, paused 2ms+2ms
04-07 18:17:52.150: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 22% free 7008K/8903K, paused 32ms
04-07 18:17:52.150: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 1584016-byte allocation
04-07 18:17:52.200: D/dalvikvm(7510): GC_FOR_ALLOC freed 0K, 4% free 8555K/8903K, paused 37ms
04-07 18:17:52.250: D/dalvikvm(7510): GC_CONCURRENT freed <1K, 4% free 8555K/8903K, paused 2ms+2ms
04-07 18:17:52.280: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 4% free 8555K/8903K, paused 30ms
04-07 18:17:52.280: I/dalvikvm-heap(7510): Grow heap (frag case) to 9.086MB for 704016-byte allocation
04-07 18:17:52.310: D/dalvikvm(7510): GC_FOR_ALLOC freed 0K, 4% free 9243K/9607K, paused 23ms
04-07 18:17:52.330: D/dalvikvm(8107): GC_CONCURRENT freed 588K, 34% free 18618K/27911K, paused 4ms+5ms
04-07 18:17:52.350: D/GC_badness(7510): 2: 360584482
04-07 18:17:52.350: D/dalvikvm(7510): GC_CONCURRENT freed 1546K, 20% free 7696K/9607K, paused 1ms+2ms
04-07 18:17:52.380: D/dalvikvm(7510): GC_FOR_ALLOC freed 688K, 28% free 7008K/9607K, paused 22ms
04-07 18:17:52.380: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 1584016-byte allocation
04-07 18:17:52.400: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 11% free 8555K/9607K, paused 21ms
04-07 18:17:52.440: D/GC_badness(7510): 3: 360584577
04-07 18:17:52.450: D/dalvikvm(7510): GC_CONCURRENT freed <1K, 4% free 9243K/9607K, paused 1ms+2ms
04-07 18:17:52.470: D/dalvikvm(7510): GC_FOR_ALLOC freed 2234K, 28% free 7008K/9607K, paused 20ms
04-07 18:17:52.470: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 1584016-byte allocation
04-07 18:17:52.500: D/dalvikvm(7510): GC_FOR_ALLOC freed 0K, 11% free 8555K/9607K, paused 29ms
04-07 18:17:52.510: D/dalvikvm(8107): GC_CONCURRENT freed 1785K, 33% free 18832K/27911K, paused 2ms+5ms
04-07 18:17:52.530: D/GC_badness(7510): 4: 360584668
04-07 18:17:52.540: D/dalvikvm(7510): GC_CONCURRENT freed <1K, 4% free 9243K/9607K, paused 1ms+2ms
04-07 18:17:52.570: D/dalvikvm(7510): GC_FOR_ALLOC freed 2234K, 28% free 7008K/9607K, paused 28ms
04-07 18:17:52.570: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 1584016-byte allocation
04-07 18:17:52.590: D/dalvikvm(7510): GC_FOR_ALLOC freed <1K, 11% free 8555K/9607K, paused 22ms
04-07 18:17:52.620: D/dalvikvm(7510): GC_CONCURRENT freed <1K, 4% free 9243K/9607K, paused 3ms+2ms
04-07 18:17:52.630: D/GC_badness(7510): 5: 360584765
04-07 18:17:52.650: D/dalvikvm(7510): GC_FOR_ALLOC freed 2235K, 28% free 7008K/9607K, paused 21ms
04-07 18:17:52.650: I/dalvikvm-heap(7510): Grow heap (frag case) to 8.416MB for 1584016-byte allocation
04-07 18:17:52.680: D/dalvikvm(7510): GC_FOR_ALLOC freed 0K, 11% free 8555K/9607K, paused 27ms
04-07 18:17:52.710: D/GC_badness(7510): 6: 360584844

【问题讨论】:

    标签: android bitmap garbage-collection heap-memory


    【解决方案1】:

    为什么要重复使用图片?

    不要给垃圾收集器收集东西的机会。基本上,您在本地定义的每个对象迟早都会被收集。

    不要重复使用您的图像变量。在您的动画代码之前制作一个图像数组和图像(最好是在创建活动期间加载)。 或者考虑为您的图片使用ObjectPool

    这是一个很好的SO answer,关于如何避免垃圾收集。

    最后,您可以找到大量关于如何避免垃圾收集的信息,例如当您使用 Google 搜索时。 “如何避免垃圾收集android”。

    【讨论】:

    • 我只是在示例代码中使用了一个图像。在应用程序中,我显示了许多图像。在高分辨率屏幕上,它们很大(1.5MB),因此预先加载很多它们是不可行的。我会很快咀嚼这堆东西。我可以分组加载它们,但如果每次加载由于 4 或 5 次 GC 而导致 100 毫秒的暂停,它们将跟不上帧速率。我很想管理自己的位图,但早期 API 中的 BitmapFactory 不支持它。没有编写自己的 jpg 加载程序来绕过 BitmapFactory 在每次调用时重新分配位图,我不确定我能做什么。
    猜你喜欢
    • 1970-01-01
    • 2011-01-18
    • 2017-03-02
    • 1970-01-01
    • 2014-05-03
    • 2019-10-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多