rub*_*com 4 .net c# vb.net ilist garbage-collection
我需要提高我的应用程序的内存性能,我可以看到我有内存碎片问题.
我读过一篇关于红门安德鲁·亨特的大型物品的有趣文章,他推荐的解决方案之一是:
如果大型数据结构需要长时间存在,特别是如果它们需要随着时间的推移而增长,那么最好的方法就是考虑使用或编写不同的数据结构来存储它们.数组在放入大对象堆之前最多可包含10,000个元素,并且可能会导致问题,因此存储100,000个条目的一种非常有效的方法可能是存储10个数组,每个数组包含10,000个元素:none将最终出现在大对象上堆,所以不会发生碎片.这可以写成
IList子类,这样可以很容易地透明地放入以替换现有代码.
如何在我的代码中实现他的建议?
我的程序有一个非常复杂的形式(一个对象在每次打开时都会留下剩余的内存.我发现了一个复杂的列表可能是罪魁祸首,我想实现他的建议,看它是否解决了这个问题.
使用List有什么问题?这只不过是IList的一个实现,你可以自己进行分区.但是如果你想透明地做到这一点:
实现IList(它只是一个接口,对它没什么特别的.也许我不明白这个问题?)并用你想要的大小的数组进行备份.Get()然后,您将获取index / sizeOfArrays包含所需项的数组的索引,并返回该数组中的index % sizeOfArrays第th项.
为了好玩,因为这是一个懒惰的星期五,我写了一些东西.注意:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)