我需要提高应用程序的内存性能,我可以看到内存碎片存在问题。
我读过Red Gate的Andrew Hunter的interesting article on large objects,他建议的解决方案之一是:
如果需要存活大型数据结构 很长一段时间,特别是如果 它们需要随着时间的推移而增长, 最好的方法就是 考虑使用或写一个不同的 存储它们的数据结构。数组 最多可容纳10,000个 他们被放在之前的元素 大对象堆,可以导致 问题,所以一个非常有效的方法 存储100,000个条目可能是 存储每个包含10,000个的10个阵列 元素:没有人会最终在 大对象堆所以没有碎片 会发生。这可以写成 一个
IList
子类,它将成为它 容易透明地落入 替换现有代码。
如何在我的代码中实现他的建议?
我的程序有一个非常复杂的形式(每次打开时都有一个剩余内存的对象。我发现一个复杂的列表可能是罪魁祸首,我想实现他的建议看它是否解决了这个问题。
答案 0 :(得分:5)
使用List有什么问题?这只不过是IList的一个实现,你可以自己进行分区。但是如果你想透明地做到这一点:
实现IList(它只是一个接口,对它没什么特别的。也许我不明白这个问题?)并用你想要的大小的数组进行备份。然后,您的Get()
会将index / sizeOfArrays
作为包含所需项目的数组的索引,并返回该数组中的index % sizeOfArrays
项。
为了好玩,因为这是一个懒惰的星期五,我写了一些东西。注意:
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;
}
}
}