大数组中的内存泄漏 - 是否会对IList进行子类化修复?

时间:2010-02-12 11:50:23

标签: c# .net vb.net garbage-collection ilist

我需要提高应用程序的内存性能,我可以看到内存碎片存在问题。

我读过Red Gate的Andrew Hunter的interesting article on large objects,他建议的解决方案之一是:

  

如果需要存活大型数据结构   很长一段时间,特别是如果   它们需要随着时间的推移而增长,   最好的方法就是   考虑使用或写一个不同的   存储它们的数据结构。数组   最多可容纳10,000个   他们被放在之前的元素   大对象堆,可以导致   问题,所以一个非常有效的方法   存储100,000个条目可能是   存储每个包含10,000个的10个阵列   元素:没有人会最终在   大对象堆所以没有碎片   会发生。这可以写成   一个IList子类,它将成为它   容易透明地落入   替换现有代码。

如何在我的代码中实现他的建议?

我的程序有一个非常复杂的形式(每次打开时都有一个剩余内存的对象。我发现一个复杂的列表可能是罪魁祸首,我想实现他的建议看它是否解决了这个问题。

1 个答案:

答案 0 :(得分:5)

使用List有什么问题?这只不过是IList的一个实现,你可以自己进行分区。但是如果你想透明地做到这一点:

实现IList(它只是一个接口,对它没什么特别的。也许我不明白这个问题?)并用你想要的大小的数组进行备份。然后,您的Get()会将index / sizeOfArrays作为包含所需项目的数组的索引,并返回该数组中的index % sizeOfArrays项。


为了好玩,因为这是一个懒惰的星期五,我写了一些东西。注意:

  • 我没有测试它
  • 我无法评论你引用的声明的正确性,这可能有助于避免内存碎片,我只是盲目地看着你的请求
  • 我不知道List或任何其他集合是否已足够聪明,只能
  • 我做出了一些可能不适合您的决定(例如,如果您现在正在使用数组,则不能盲目地将其删除。请查看Item实现,尤其是setter,例如

那就是说,这是一个减少周末前动机不足的起点。我给亲爱的读者(或OP)留下了一些有趣的方法作为练习..; - )

public class PartitionList<T> : IList<T> {
    private readonly int _maxCountPerList;
    private readonly IList<IList<T>> _lists;

    public PartitionList(int maxCountPerList) {
        _maxCountPerList = maxCountPerList;
        _lists = new List<IList<T>> { new List<T>() };
    }

    public IEnumerator<T> GetEnumerator() {
        return _lists.SelectMany(list => list).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }

    public void Add(T item) {
        var lastList = _lists[_lists.Count - 1];
        if (lastList.Count == _maxCountPerList) {
            lastList = new List<T>();
            _lists.Add(lastList);
        }
        lastList.Add(item);
    }

    public void Clear() {
        while (_lists.Count > 1) _lists.RemoveAt(1);
        _lists[0].Clear();
    }

    public bool Contains(T item) {
        return _lists.Any(sublist => sublist.Contains(item));
    }

    public void CopyTo(T[] array, int arrayIndex) {
        // Homework
        throw new NotImplementedException();
    }

    public bool Remove(T item) {
        // Evil, Linq with sideeffects
        return _lists.Any(sublist => sublist.Remove(item));
    }

    public int Count {
        get { return _lists.Sum(subList => subList.Count); }
    }

    public bool IsReadOnly {
        get { return false; }
    }

    public int IndexOf(T item) {
        int index = _lists.Select((subList, i) => subList.IndexOf(item) * i).Max();
        return (index > -1) ? index : -1;
    }

    public void Insert(int index, T item) {
        // Homework
        throw new NotImplementedException();
    }

    public void RemoveAt(int index) {
        // Homework
        throw new NotImplementedException();
    }

    public T this[int index] {
        get {
            if (index >= _lists.Sum(subList => subList.Count)) {
                throw new IndexOutOfRangeException();
            }
            var list = _lists[index / _maxCountPerList];
            return list[index % _maxCountPerList];
        }
        set {
            if (index >= _lists.Sum(subList => subList.Count)) {
                throw new IndexOutOfRangeException();
            }
            var list = _lists[index / _maxCountPerList];
            list[index % _maxCountPerList] = value;
        }
    }
}