GC收集......什么?

时间:2009-12-23 10:59:55

标签: c# garbage-collection memory-management slimdx

我正在尝试优化我的引擎(C#+ SlimDX)以尽可能减少分配(以防止GC过于频繁地触发),并使用分析器作为指导,该分析器为我提供了生成包含对象的位置。它的进展非常顺利(从每隔5分钟下降到20 MB,每1分钟一次,每次运行8 MB(是的,这是非常优化的XD)) 有一种方法,我找不到任何声明的东西,我不知道该怎么做。看起来这个方法在它的主体中每次执行都会产生2个受控对象(而不是在被调用的函数上):

有人可以指导我理解为什么这个函数会产生被污染的对象吗?我真的没有线索。

    public override void Update()
    {
        base.Update();
        if (LastCheckInstancesNumber != Instances.Count)
        {
            LastCheckInstancesNumber = Instances.Count;
            _needToRegenerateUpdate = true;
        }
        // Crea byte array da usare nel prossimo draw.
        if (_needToRegenerateUpdate)
        {
            Int32 PrimitivesCount = Instances.Count;
            Int32 Size = PrimitivesCount * 80;

            if ((ByteUpdateTemp != null) && (ByteUpdateTemp.Length < Size))
                ByteUpdateTemp = new byte[Size];
            int offset = 0;

            PrimitivesCount = 0;
            Int32 Count = Instances.Count;
            for (int i = 0; i < Count; i++)
            {
                InstancedBase3DObjectInstanceValues ib = Instances[i];
                if (ib.Process)
                {
                    MathHelper.CopyMatrix(ref ib._matrix, ref MatrixTemp);
                    MathHelper.CopyVector(ref ib._diffuseColor, ref ColorTemp);

                    ObjectUpdateTemp[0] = MatrixTemp.M11;
                    ObjectUpdateTemp[1] = MatrixTemp.M12;
                    ObjectUpdateTemp[2] = MatrixTemp.M13;
                    ObjectUpdateTemp[3] = MatrixTemp.M14;
                    ObjectUpdateTemp[4] = MatrixTemp.M21;
                    ObjectUpdateTemp[5] = MatrixTemp.M22;
                    ObjectUpdateTemp[6] = MatrixTemp.M23;
                    ObjectUpdateTemp[7] = MatrixTemp.M24;
                    ObjectUpdateTemp[8] = MatrixTemp.M31;
                    ObjectUpdateTemp[9] = MatrixTemp.M32;
                    ObjectUpdateTemp[10] = MatrixTemp.M33;
                    ObjectUpdateTemp[11] = MatrixTemp.M34;
                    ObjectUpdateTemp[12] = MatrixTemp.M41;
                    ObjectUpdateTemp[13] = MatrixTemp.M42;
                    ObjectUpdateTemp[14] = MatrixTemp.M43;
                    ObjectUpdateTemp[15] = MatrixTemp.M44;
                    ObjectUpdateTemp[16] = ColorTemp.X;
                    ObjectUpdateTemp[17] = ColorTemp.Y;
                    ObjectUpdateTemp[18] = ColorTemp.Z;
                    ObjectUpdateTemp[19] = ColorTemp.W;
                    ByteConverter.WriteSingleArrayToByte(ref ObjectUpdateTemp, ref ByteUpdateTemp, offset);
                    offset += 20;

                    PrimitivesCount++;
                }
            }

            SynchronizedObject so = SynchronizationEventWriter.LockData();
            so.Synchronizedobject = ByteUpdateTemp;
            SynchronizationEventWriter.Update();
            SynchronizationEventWriter.UnlockData();
            _needToRegenerateUpdate = false;

            so = SynchronizationEventWriterNum.LockData();
            so.Synchronizedobject = PrimitivesCount;
            SynchronizationEventWriterNum.Update();
            SynchronizationEventWriterNum.UnlockData();
        }
  }

注意:

由于缓存,永远不会调用新字节[Size]。 MathHelper函数只是将每个元素(Single)从一个对象复制到另一个对象而不创建任何东西。 base.Update()几乎什么也没做(而且无论如何都是从我的引擎中的ALL对象派生出来的,但只有在这里我才有垃圾对象)

感谢!!!

编辑:

    internal void GetLock()
    {
        Monitor.Enter(InternalLock);
        Value.Locked = true;
        Value.LockOwner = Thread.CurrentThread;
    }
    public SynchronizedObject LockData()
    {
        Parent.GetLock();
        return Parent.Value;
    }

这是LockData()的代码。我认为它不会产生任何结果:|

3 个答案:

答案 0 :(得分:2)

我已经解决了!!!

问题是so.Synchronizedobject = PrimitivesCount;将Int32分配给Object类。似乎这会在每次导致旧对象被吞噬的对象时替换。 我通过使用box类来封装Int32对象并简单地更改其中的值来解决。

答案 1 :(得分:1)

什么在base.Update(),什么?

你的探查器可以转储堆吗?如果是这样的话,为什么我会在这个方法之前放置一个断点并转储堆然后再直接。这样你就可以看到创建了什么类型的对象。

没有一种蛮力的方式逐行评论是另一种(可怕的)想法。

您的MathHelper方法是否会创建临时对象?

答案 2 :(得分:0)

我只是猜测,但看起来你在该函数的底部九行中创建了两个SynchronizedObject对象:

SynchronizedObject so = SynchronizationEventWriter.LockData();

so = SynchronizationEventWriterNum.LockData();

没有详细了解SynchronizedObject或LockData()是否实际创建了任何内容,但它是我在代码中看到的唯一选择......