Утечка памяти в большом массиве - это исправит подкласс IList? - PullRequest
4 голосов
/ 12 февраля 2010

Мне нужно улучшить производительность памяти в моем приложении, и я вижу, что у меня проблемы с фрагментацией памяти.

Я прочитал интересную статью о больших объектах от Эндрю Хантера из Red Gate, и одно из рекомендуемых им решений:

Если большие структуры данных должны жить в течение длительного времени, и особенно если они должны расти в размерах с течением времени, лучший подход просто рассмотреть возможность использования или написания другого структура данных для их хранения. Массивы может содержать до 10000 элементы, прежде чем они надеты большой объект куча и может вызвать проблемы, поэтому очень эффективный способ хранить 100 000 записей может быть хранить 10 массивов, каждый из которых содержит 10 000 элементы: ни один не будет в конечном итоге на куча больших объектов, поэтому нет фрагментации произойдет. Это можно записать как IList подкласс, который сделал бы это легко вставлять прозрачно заменить существующий код.

Как мне реализовать его предложение в моем коде?

Моя программа имеет очень сложную форму (с объектом, который оставляет остаточную память при каждом открытии. Я нашел сложный список, который может быть виновником, и я хотел бы реализовать его предложение посмотрите, решит ли это проблему.

1 Ответ

5 голосов
/ 12 февраля 2010

Что не так с использованием списка для этого?Это не что иное, как реализация IList, и вы можете выполнить разбиение самостоятельно.Но если вы хотите сделать это прозрачно:

Реализация IList (это просто интерфейс, ничего особенного. Может быть, я не понимаю вопроса?) И резервное копирование массивов желаемого размера.Затем ваш Get() примет index / sizeOfArrays в качестве индекса массива, содержащего нужный элемент, и вернет index % sizeOfArrays -й элемент в этом массиве.


Ради интереса, потому что это ленивая пятница,Я написал кое-что.Примечание:

  • Я не проверял это
  • Я не могу прокомментировать правильность ваших утверждений о том, что это может помочь избежать фрагментации памяти, я просто слепо посмотрел на ваш запрос
  • Я не знаю, является ли List или какая-либо другая коллекция достаточно умной, чтобы делать именно это
  • Я принял некоторые решения, которые могут не подходить вам (то есть вы не можете слепо отбросить это в своем кодеесли вы сейчас используете массивы. Посмотрите на реализацию Item, особенно на сеттер, например

Тем не менее, вот отправная точка, которая уменьшила мой мотивационный дефицит перед выходными. Я оставил некоторыеинтересные приемы как упражнение дорогому читателю (или ОП) ..; -)

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;
        }
    }
}
...