【问题标题】:GC collecting...what?GC 收集...什么?
【发布时间】:2009-12-23 10:59:54
【问题描述】:

我正在尝试优化我的引擎 (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 函数只是将每个元素(单个)从一个对象复制到另一个对象,而无需创建任何内容。 base.Update() 几乎什么都不做(无论如何都是从我的引擎中的所有对象派生的,但只有在这里我有垃圾对象)

谢谢!!!

编辑:

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

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

【问题讨论】:

  • 只是猜测,但 SynchronizedObject 确实如此 = SynchronizationEventWriter.LockData();返回一个新实例?
  • 不,返回对受监视器保护的对象的引用。

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


【解决方案1】:

我解决了!!!

问题在于 so.Synchronizedobject = PrimitivesCount;将 Int32 分配给 Object 类。似乎每次导致旧对象被垃圾的对象时都会替换。 我通过使用一个盒子类来封装 Int32 对象并简单地更改里面的值来解决。

【讨论】:

    【解决方案2】:

    base.Update() 中有什么?

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

    除此之外,逐行注释的蛮力方法是另一个(可怕的)想法。

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

    【讨论】:

    • 它只说我:System.Int32 (+1 object + 12 bytes) Int32 算作对象吗? :|
    • 尝试使用预分配的 Int32,但没有发生任何变化
    • 嗯,Int32 不是值类型,因此只能在堆栈上分配(除非它是作为堆上对象的一部分的字段)。
    【解决方案3】:

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

    SynchronizedObject so = SynchronizationEventWriter.LockData();
    

    so = SynchronizationEventWriterNum.LockData();
    

    没有关于 SynchronizedObject 或 LockData() 是否真的创建任何东西的详细知识,但这是我在您的代码中看到的唯一选择...

    【讨论】:

    • 我发布了调用的代码,它没有任何作用...Parent.Value 是一个简单的属性(get;set;)
    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    • 2012-01-31
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    相关资源
    最近更新 更多