4

アプリケーションのメモリ パフォーマンスを改善する必要があるのですが、メモリの断片化に問題があることがわかりました。

Red Gate の Andrew Hunter によるラージ オブジェクトに関する興味深い記事を読みましたが、彼が推奨する解決策の 1 つが次のとおりです。

大規模なデータ構造を長期間存続させる必要がある場合、特に時間の経過とともにサイズを大きくする必要がある場合は、別のデータ構造を使用または作成して格納することを検討するのが最善の方法です。配列は、大きなオブジェクト ヒープに置かれる前に最大で約 10,000 の要素を含むことができ、問題を引き起こす可能性があります。そのため、100,000 のエントリを保存する非常に効果的な方法は、それぞれが 10,000 の要素を含む 10 個の配列を保存することです。大きなオブジェクトには最終的に何も含まれません。断片化が発生しないようにします。これはサブクラスとして記述でき、IList既存のコードを透過的に置き換えることが容易になります。

彼の提案を自分のコードに実装するにはどうすればよいですか?

私のプログラムには非常に複雑な形式があります (開くたびに残りのメモリを残すオブジェクトを使用します)。犯人である可能性のある複雑なリストを見つけました。彼の提案を実装して、問題が解決するかどうかを確認したいと思います。

4

1 に答える 1

5

そのためにリストを使用することの何が問題になっていますか?これはIListの実装に他ならず、自分でパーティショニングを行うことができます。しかし、透過的に実行したい場合は、次のようにします。

IListを実装し(これは単なるインターフェイスであり、特別なことは何もありません。質問がわからないのではないでしょうか?)、希望のサイズの配列でバックアップします。Get()次に、目的のアイテムindex / sizeOfArraysを含む配列のインデックスとして取得し、index % sizeOfArraysその配列のthアイテムを返します。


楽しみのために、それは怠惰な金曜日なので、私は何かを書きました。ノート:

  • 私はそれをテストしませんでした
  • これがメモリの断片化を回避するのに役立つかもしれないというあなたの引用された主張の正しさについてコメントすることはできません、私はあなたの要求を盲目的に見ました
  • リストや他のコレクションがすでにそれを行うのに十分賢いのかどうかはわかりません
  • 私はあなたに適さないかもしれないいくつかの決定をしました(つまり、現在配列を使用している場合、これをコードに盲目的にドロップすることはできません。Itemたとえば、実装、特にセッターを見てください

そうは言っても、週末前のやる気を起こさせる赤字を減らした出発点はここにあります。親愛なる読者(または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;
        }
    }
}
于 2010-02-12T12:09:22.797 に答える