为什么我的代码导致非托管内存慢慢增加导致gen0集合?

时间:2015-03-14 21:19:40

标签: c# dictionary memory-leaks enumerator dotpeek

当我在单元测试中运行以下代码时,我发现性能监视器中的私有字节和工作集缓慢增加,并且非托管内存在dotMemory中缓慢上升。我在dotPeek中反编译了源代码,似乎无法找到任何与众不同的东西。有任何想法吗?这是代码:

[TestMethod]
    public void TestEnumeratorMoveNext()
    {
        //Dictionary<string, int>[] outDict = new Dictionary<string, int>[32].Select(x => x = new int[100].ToDictionary(y => Guid.NewGuid().ToString())).ToArray();
        var outDict = new Dictionary<string, int>[32];
        for (int j = 0; j < 32; j++)
        {
            outDict[j] = new Dictionary<string, int>();
            for(int q = 0; q < 100; q++)
            {
                outDict[j].Add(Guid.NewGuid().ToString(), 0);
            }
        }

        for (int i = 0; i < 10000; i++)
        {
            var enumerator = new Enumerator<string, int>(outDict);

            while (enumerator.MoveNext()) { }

            Thread.Sleep(1000 / 60);
        }
    }

    public struct Enumerator<TKey, TValue> : IEnumerator<KeyValuePair<TKey, TValue>>
    {
        private Dictionary<TKey, TValue>[] dictionary;

        private int partition;
        private IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
        private bool moveNext;

        private int totalPartitions;

        internal Enumerator(Dictionary<TKey, TValue>[] dictionary)
        {
            this.dictionary = dictionary;
            this.totalPartitions = dictionary.Count();

            partition = 0;
            enumerator = new Dictionary<TKey, TValue>.Enumerator();
            moveNext = false;
        }

        public bool MoveNext()
        {

            if (partition < totalPartitions)
            {
                do
                {
                    var outDict = dictionary[partition];

                    if (!moveNext)
                        enumerator = outDict.GetEnumerator();

                    moveNext = enumerator.MoveNext();

                    if (!moveNext)
                    {
                        enumerator.Dispose();
                        partition++;
                    }
                } while (!moveNext && partition < totalPartitions);

                return true;
            }

            partition = totalPartitions + 1;
            enumerator = new Dictionary<TKey, TValue>.Enumerator();
            moveNext = false;
            return false;
        }

        public KeyValuePair<TKey, TValue> Current
        {
            get
            {
                return enumerator.Current;
            }
        }

        public void Dispose()
        {
            enumerator.Dispose();
        }

        object IEnumerator.Current
        {
            get
            {
                return new KeyValuePair<TKey, TValue>(Current.Key, Current.Value);
            }
        }

        public void Reset()
        {
            throw new NotSupportedException();
        }
    }

我感谢任何人都能给我的帮助。提前谢谢。

1 个答案:

答案 0 :(得分:0)

解决方案是在Enumerator结构中将private IEnumerator<KeyValuePair<TKey, TValue>> enumerator更改为private Dictionary<TKey, TValue>.Enumerator enumerator。不再有G0 GC。如果有人知道为什么会这样,我很乐意听到解释。