1

我正在处理一个 SDK,它保留对它创建的每个对象的引用,只要主连接对象在范围内。定期创建新的连接对象会导致其他资源问题,这不是一种选择。

为了做我需要做的事情,我必须遍历数千个这样的对象(将近 100,000 个),虽然我当然不会保留对这些对象的引用,但我正在使用的 SDK 中的对象模型会这样做。这会咀嚼内存并且危险地接近导致 OutOfMemoryExceptions。

这些对象存储在嵌套的 ReadOnlyCollections 中,所以我现在正在尝试使用反射将其中一些集合设置为空,当我完成它们时,垃圾收集器可以收集使用的内存。

foreach (Build build in builds)
{
        BinaryFileCollection numBinaries = build.GetBinaries();
        foreach (BinaryFile binary in numBinaries)
        {
            this.CoveredBlocks += binary.HitBlockCount;
            this.TotalBlocks += binary.BlockCount;
            this.CoveredArcs += binary.HitArcCount;
            this.TotalArcs += binary.ArcCount;

            if (binary.HitBlockCount > 0)
            {
                this.CoveredSourceFiles++;
            }

            this.TotalSourceFiles++;

            foreach (Class coverageClass in binary.GetClasses())
            {
                if (coverageClass.HitBlockCount > 0)
                {
                    this.CoveredClasses++;
                }

                this.TotalClasses++;

                foreach (Function function in coverageClass.GetFunctions())
                {
                    if (function.HitBlockCount > 0)
                    {
                        this.CoveredFunctions++;
                    }

                    this.TotalFunctions++;
                }
            }

            FieldInfo fi = typeof(BinaryFile).GetField("classes", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(binary, null);
    }

当我检查 numBinaries[0] 中的类成员的值时,它返回 null,这似乎完成了任务,但是当我运行此代码时,内存消耗只会不断上升,就像我不运行时一样快将类设置为 null 。

我想弄清楚的是这种方法是否存在本质上的缺陷,或者是否有另一个对象保留对我缺少的类 ReadOnlyCollection 的引用。

4

1 回答 1

0

我可以想到几个替代方案...

  1. 逻辑上把它分开。您提到它“在连接期间”保留所有引用。你能做 10%,关闭它,打开一个新的,跳过那 10%,再拿 10%(总共 20%),等等?
  2. 我们在这里谈论多少内存,这个工具是否会长期存在?那么如果它在几分钟内使用大量 RAM 怎么办?你真的得到了OOM吗?如果您的系统有那么多可用的 RAM 供程序使用,为什么不使用它呢?您为 RAM 付费。这让我想起了 Raymond Chen 的一篇关于 100% CPU 消耗的博文。
  3. 如果你真的想看看是什么阻止了垃圾收集,启动 SOS 并使用!gcroot是一个开始的地方。

但是尽管如此,如果这确实是一个问题,我会花更多时间与第 3 方 API 提供商合作——在某些时候他们可能会发布你想要的更新来打破这个——你会回到原点,或者更糟糕的是,您可能会在产品中引入细微的错误。

于 2011-03-08T21:27:35.120 回答