【问题标题】:Why so many GC_FOR_ALLOC in a simple app?为什么在一个简单的应用程序中有这么多 GC_FOR_ALLOC?
【发布时间】:2013-12-11 11:29:06
【问题描述】:

我从 dalvikvm 获得了太多的 GC_FOR_ALLOC。 我从 REST 服务获取 XML:在一项活动中,我以编程方式(我)解析了大约 100 行,而在另一项活动中,我使用 SimpleXML 解析了大约 200 行。

在第一个中,我得到 50 GC_FOR_ALLOC。 在第二个我得到像300! (我什至不能全部发布,正文有 29579 个字符,只允许 30k)

我搜索过,几乎每个人都抱怨 gc_for_"M"alloc 而不是 gc_for_"A"lloc。

SimpleXML 的问题是因为创建了实例吗?

我将通过 dalvikvm 发布 logcat 转储,也许这些值有一些信息。

非常感谢您的帮助。

12-11 06:13:49.564: D/dalvikvm(6759): GC_FOR_ALLOC freed 362K, 13% free 4116K/4688K, paused 181ms, total 182ms
12-11 06:13:50.074: D/dalvikvm(6759): GC_FOR_ALLOC freed 303K, 13% free 4134K/4708K, paused 142ms, total 142ms
.... repeated many times .....
12-11 06:14:06.254: D/dalvikvm(6759): GC_FOR_ALLOC freed 73K, 13% free 4159K/4768K, paused 53ms, total 53ms
12-11 06:14:06.314: D/dalvikvm(6759): GC_FOR_ALLOC freed 103K, 13% free 4159K/4768K, paused 56ms, total 57ms
12-11 06:14:06.374: D/dalvikvm(6759): GC_FOR_ALLOC freed 29K, 12% free 4203K/4768K, paused 54ms, total 54ms
12-11 06:14:06.424: D/dalvikvm(6759): GC_FOR_ALLOC freed 73K, 13% fre

【问题讨论】:

  • 没有你的代码很难调试你的代码。
  • 例如,如果您使用 Google 地图,您会收到很多此类消息,而您却无能为力。我对消息使用过滤器(通过日志消息):^(?!.*(GC_)|(Cache)).*$
  • 你是在循环内实例化一个对象吗?
  • 在第一个 XML 中,是的,我在循环中实例化 Scanner,以便我可以逐行解析这些行,但这并不是最糟糕的“问题”。在第二个中,我使用 SimpleXML 框架“反序列化”,不知道代码,但我认为如果解析 XML,它必须创建一些实例。
  • 我没有使用谷歌地图。我想知道是否有什么非常错误和明显的地方。

标签: android performance dalvik


【解决方案1】:

您可以使用 DDMS 分配跟踪器(memory debugging docs、旧的blog postddms docs)查看最近分配的对象。这将向您显示正在分配的内容,并为您提供执行分配位置的堆栈跟踪。

Another blog post 描述了 MAT 和其他相关工具,尽管堆转储分析对此类问题的用处不大,因为它通常会显示尚未被释放的对象,而你'对正在被释放的对象更感兴趣。

【讨论】:

  • 我已经使用过它,但没有足够的对象来连续释放 300 次 344Kb,我也无法在我的程序中实例化这样的“巨大”对象(在此上下文中)。一定有别的东西。我使用模拟器的事实可能是原因吗?谢谢fadden!
  • 分配跟踪器仅显示所选应用程序的最近 512 个分配。如果您在繁忙的应用程序运行时抓取它的快照,您应该能够了解所有正在分配的内容。此外,请确保您正在观看正确的应用程序 - 将日志文件中的进程 ID(在您的示例中为 6759)与应用程序的“信息”面板上显示的内容进行比较。
【解决方案2】:

在 Android Dalvik VM 中,当 dlmalloc 占用空间不足以容纳 new 或 heap->bytesAllocated + n > hs->softLimit 时,GC_FOR_ALLOC 会在 object alloc step 中被调用。您可以将dalvik.system.setTargetHeapUtilization 设置得更低以获得更多可用堆空间。

【讨论】:

    【解决方案3】:

    您可以使用 MAT MAT tutorial

    找出有多少对象正在创建和垃圾收集。这样你就可以优化你的代码

    【讨论】:

    • 谢谢,我试试。我必须说我正在使用模拟器,我无法安装驱动程序,因为我不是管理员,并且管理员没有设法为我的 Nexus S 安装它(这有点棘手)。可能与问题有关?
    【解决方案4】:

    如果您在应用滞后时收到多个GC_FOR_ALLOC,则该错误很可能处于循环中。检查代码行从哪里开始触发 GC,然后从那里开始跟踪代码。根据我的经验,我输入错误的内部循环迭代器会导致程序进行无限循环。我创建了一个这样的错误:

    for(int i=0; i<list.size(); i++) {
         for(int j=i+1 j<list.size(); i++) {
    
         // I mistyped the iterator of integer j with i
         // making an infinite loop which triggered the GC.
         //appears many times
    
         }
    }
    

    【讨论】:

      【解决方案5】:

      我今天遇到了同样的问题。 我在我的代码中发现了一个未结束的循环,例如 while(i

      【讨论】:

      • 感谢您的关心,但没有这样的事情。 Dalvik VM 的工作方式导致了这一点。我前段时间写了这个问题,所以我不太记得发生了什么。我能说的是,内存在 Android 中是一个真正的问题,我们应该始终非常小心!
      【解决方案6】:

      我的日志:

      D/dalvikvm: GC_FOR_ALLOC freed 549K, 9% free 7878K/8596K, paused 30ms, total 34ms
      
      ...freed 539K, 9% free 7888K/8596K, paused 30ms, total 30ms
      ...freed 1856K, 21% free 8083K/10108K, paused 51ms, total 51ms
      ...freed 582K, 9% free 7845K/8596K, paused 38ms, total 38ms
      

      解释:

      当您的应用获得内存时,每个应用都会受到更多限制。 Dalvik/Ant 调用垃圾收集器。

      是什么限制了您的应用程序的内存决定 Dalvik/Ant。正如您在我的应用中看到的,Dalvik 决定 8596K(双箱)和 8083K(单箱)。

      并限制运行时的变化。

      而且您无法确定何时会发生这种情况。但是你可以减少这种可能性。减少应用程序消耗的内存量。

      PS: 决定什么时候调用 GC 需要 Dalvik/Ant。而且您无法确定何时会发生这种情况。但是你可以减少这种可能性。减少应用程序消耗的内存量。

      PS:在“Monitor android”中查看标签“Monitors”,图形“Memory”。并使用按钮:“暂停(启用)”、“启动 GC”、“转储 Java 堆”“开始 Alocation Tracking(非常有用)”。并为此使用官方指南:

      https://developer.android.com/studio/profile/am-memory.html?utm_source=android-studio.

      据我了解,当 VM 调用 GC 时,应用程序不得停止/暂停工作或崩溃

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 2021-02-05
        • 1970-01-01
        相关资源
        最近更新 更多