一段时间后,GC包含许多固定对象

时间:2021-05-23 19:44:21

I have a strange phenomenon while continuously instantiating a com-wrapper and then letting the GC collect it (not forced).

我有一个奇怪的现象,同时连续实例化一个com-wrapper,然后让GC收集它(不强制)。

I'm testing this on .net cf on WinCE x86. Monitoring the performance with .net Compact framework remote monitor. Native memory is tracked with Windows CE Remote performance monitor from the platform builder toolkit.

我正在WinCE x86上测试.net cf。使用.net Compact框架远程监视器监视性能。使用平台构建器工具包中的Windows CE远程性能监视器跟踪本机内存。

During the first 1000 created instances every counter in perfmon seems ok:

在前1000个创建的实例中,perfmon中的每个计数器似乎都可以:

  • GC heap goes up and down but the average remains the same
  • GC堆上升和下降但平均值保持不变

  • Pinned objects is 0
  • 固定对象为0

  • native memory keeps the same average
  • 本机内存保持相同的平均值

  • ...

However, after those 1000 (approximately) the Pinned object counter goes up and never goes down in count ever again. The memory usage stays the same however.

然而,在那些1000(大约)之后,Pinned对象计数器上升并且永远不会再次计数。但是内存使用情况保持不变。

I don't know what conclusion to pull from this information... Is this a bug in the counters, is this a bug in my software?

我不知道从这些信息中得出什么结论......这是计数器中的错误,这是我软件中的错误吗?

[EDIT]

I do notice that the Pinned objects counter starts to go up as soon the total bytes in use after GC stabilises as does the Objects not moved by compactor counter.

我注意到固定对象计数器在GC稳定后使用的总字节很快就会开始上升,而压缩机计数器没有移动的对象也是如此。

The graphic of the counters http://files.stormenet.be/gc_pinnedobj.jpg

计数器的图形http://files.stormenet.be/gc_pinnedobj.jpg

[/EDIT]

Here's the involved code:

这是涉及的代码:

    private void pButton6_Click(object sender, EventArgs e) {
        if (_running) {
            _running = false;
            return;
        }
        _loopcount = 0;
        _running = true;

        Thread d = new Thread(new ThreadStart(LoopRun));
        d.Start();
    }

    private void LoopRun() {
        while (_running) {
            CreateInstances();
            _loopcount++;
            RefreshLabel();
        }
    }

    void CreateInstances() {
        List<Ppb.Drawing.Image> list = new List<Ppb.Drawing.Image>();
        for (int i = 0; i < 10; i++) {
            Ppb.Drawing.Image g = resourcesObj.someBitmap;
            list.Add(g);
        }

    }

The Image object contains an AlphaImage:

Image对象包含一个AlphaImage:

    public sealed class AlphaImage : IDisposable {
    IImage _image;
    Size _size;
    IntPtr _bufferPtr;

    public static AlphaImage CreateFromBuffer(byte[] buffer, long size) {
        AlphaImage instance = new AlphaImage();
        IImage img;
        instance._bufferPtr = Marshal.AllocHGlobal((int)size);
        Marshal.Copy(buffer, 0, instance._bufferPtr, (int)size);
        GetIImagingFactory().CreateImageFromBuffer(instance._bufferPtr, (uint)size, BufferDisposalFlag.BufferDisposalFlagGlobalFree, out img);
        instance.SetImage(img);
        return instance;
    }

    void SetImage(IImage image) {
        _image = image;
        ImageInfo imgInfo;
        _image.GetImageInfo(out imgInfo);
        _size = new Size((int)imgInfo.Width, (int)imgInfo.Height);
    }

    ~AlphaImage() {
        Dispose();
    }

    #region IDisposable Members

    public void Dispose() {
        Marshal.FinalReleaseComObject(_image);
    }
}

2 个解决方案

#1


3  

I doubt it's a bug in RPM. What we don't have here is any insight into the Ppb.Drawing stuff. The place I see for a potential problem is the GetIImagingFactory call. What does it do? It's probably just a singleton getter, but it's something I'd chase.

我怀疑这是RPM中的一个错误。我们这里没有的是对Ppb.Drawing东西的任何见解。我看到潜在问题的地方是GetIImagingFactory调用。它有什么作用?它可能只是一个单身的吸气剂,但它是我追逐的东西。

I also see an AllochHGlobal, but nowhere do I see that allocation getting freed. For now that's where I'd focus.

我也看到了一个AllochHGlobal,但我没有看到该分配被释放。现在,这是我关注的地方。

#2


4  

Well, there's a bug in your code in that you're creating a lot of IDisposable instances and never calling Dispose on them. I'd hope that the finalizers would eventually kick in, but they shouldn't really be necessary. In your production code, do you dispose of everything appropriately - and if not, is there some reason why you can't?

好吧,您的代码中存在一个错误,即您正在创建大量IDisposable实例并且从不在它们上调用Dispose。我希望终结者最终能够进入,但他们不应该是必要的。在您的生产代码中,您是否妥善处理了所有事情 - 如果没有,是否有某些原因导致您不能?

If you put some logging in the AlphaImage finalizer (detecting AppDomain unloading and application shutdown and not logging in those cases!) does it show the finalizer being called?

如果你在AlphaImage终结器中放入一些日志记录(检测AppDomain卸载和应用程序关闭而不记录那些情况!)它是否显示调用终结器?

EDIT: One potential problem which probably isn't biting you, but may be worth fixing anyway - if the call to CreateImageFromBuffer fails for whatever reason, you still own the memory created by AllocHGlobal, and that will currently be leaked. I suspect that's not the problem or it would be blowing up more spectacularly, but it's worth thinking about.

编辑:一个可能没有咬你的潜在问题,但无论如何都可能值得修复 - 如果对CreateImageFromBuffer的调用因任何原因失败,你仍然拥有AllocHGlobal创建的内存,而且目前会被泄露。我怀疑这不是问题,或者它会更加壮观,但值得思考。

#1


3  

I doubt it's a bug in RPM. What we don't have here is any insight into the Ppb.Drawing stuff. The place I see for a potential problem is the GetIImagingFactory call. What does it do? It's probably just a singleton getter, but it's something I'd chase.

我怀疑这是RPM中的一个错误。我们这里没有的是对Ppb.Drawing东西的任何见解。我看到潜在问题的地方是GetIImagingFactory调用。它有什么作用?它可能只是一个单身的吸气剂,但它是我追逐的东西。

I also see an AllochHGlobal, but nowhere do I see that allocation getting freed. For now that's where I'd focus.

我也看到了一个AllochHGlobal,但我没有看到该分配被释放。现在,这是我关注的地方。

#2


4  

Well, there's a bug in your code in that you're creating a lot of IDisposable instances and never calling Dispose on them. I'd hope that the finalizers would eventually kick in, but they shouldn't really be necessary. In your production code, do you dispose of everything appropriately - and if not, is there some reason why you can't?

好吧,您的代码中存在一个错误,即您正在创建大量IDisposable实例并且从不在它们上调用Dispose。我希望终结者最终能够进入,但他们不应该是必要的。在您的生产代码中,您是否妥善处理了所有事情 - 如果没有,是否有某些原因导致您不能?

If you put some logging in the AlphaImage finalizer (detecting AppDomain unloading and application shutdown and not logging in those cases!) does it show the finalizer being called?

如果你在AlphaImage终结器中放入一些日志记录(检测AppDomain卸载和应用程序关闭而不记录那些情况!)它是否显示调用终结器?

EDIT: One potential problem which probably isn't biting you, but may be worth fixing anyway - if the call to CreateImageFromBuffer fails for whatever reason, you still own the memory created by AllocHGlobal, and that will currently be leaked. I suspect that's not the problem or it would be blowing up more spectacularly, but it's worth thinking about.

编辑:一个可能没有咬你的潜在问题,但无论如何都可能值得修复 - 如果对CreateImageFromBuffer的调用因任何原因失败,你仍然拥有AllocHGlobal创建的内存,而且目前会被泄露。我怀疑这不是问题,或者它会更加壮观,但值得思考。