非常に奇妙な問題が発生している。したがって、背景は、Word ContentControl
と、そのコントロール内のコンテンツに関連する情報を格納するために使用するカスタムオブジェクトとの間のマッピングがあることです。このマッピングを維持するには、SortedList<ContentControl, OurCustomObject>
を使用します。 SortedListパーツは、コンテンツコントロールに関連付けられたオブジェクトにすばやくアクセスできるだけでなく、次/以前のコンテンツコントロールを見つけることができる場合に便利です。 Rangeにアクセスする。ループ内で開始するとCompareerのパフォーマンスが向上する
var dictOfObjs = Globals.ThisAddIn.Application.ActiveDocument.ContentControls
.Cast<ContentControl>()
.ToDictionary(key => key, elem => new OurCustomObject(elem));
var comparer = Comparer<ContentControl>
.Create((x, y) => x.Range.Start.CompareTo(y.Range.Start));
var list = new SortedList<ContentControl, OurCustomObject>(dictOfObjs, storedcomparer);
これをかなりうまく動作するように見えますが、私は最近〜5000のコンテンツコントロールを持つ文書でそれを試みたが、それは絶対に鈍化しましたクロール(SortedListをインスタンス化するために3分以上)。
これで不思議ですが、まだまだ違和感はまだありません。私は、何が起きているのかを把握するためにいくつかのログを追加しました。リストの中でそれぞれContentControl
の開始を記録すると、約60倍のスピードでそれが始まることがわかりました。 (はい、ロギングを追加するとスピードアップしました!)。ここでははるかに高速のコードは次のとおりです。
var dictOfObjs = Globals.ThisAddIn.Application.ActiveDocument.ContentControls
.Cast<ContentControl>()
.ToDictionary(key => key, elem => new OurCustomObject(elem));
foreach (var pair in dictOfObjs)
{
_logger.Debug("Start: " + pair.Key.Range.Start);
}
var comparer = Comparer<ContentControl>
.Create((x, y) => x.Range.Start.CompareTo(y.Range.Start));
var list = new SortedList<ContentControl, OurCustomObject>(dictOfObjs, storedcomparer);
SortedListのためのコンストラクタは、辞書のキーと値にArray.Sort<TKey, TValue>(keys, values, comparer);
を呼び出します。 Rangeオブジェクトにループでアクセスして、あらかじめ高速化するのはなぜか分かりません。おそらく、アクセスされる順番と何か関係がありますか? foreachループは、ドキュメントに表示されている順序でそれらにアクセスし、Array.Sortは、すべての上をホップします。
編集:SortedListと言うとき、私はSystem.Collections.Generic.SortedList<TKey, TValue>
を意味します。ここで私が使用して、コンストラクタのコードです:
public SortedList(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
: this((dictionary != null ? dictionary.Count : 0), comparer) {
if (dictionary==null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
dictionary.Keys.CopyTo(keys, 0);
dictionary.Values.CopyTo(values, 0);
Array.Sort<TKey, TValue>(keys, values, comparer);
_size = dictionary.Count;
}
SortedListコンストラクタコードを提供できますか?それがスローダウンが起こっている場所であれば、それは私たちが見なければならないものです.Wordの既知の問題は、foreachの代わりに+ indexを使ってループするほうが速いことです。私は、それは単にインデックスを使ってWordを取り上げるのではなく、オブジェクトがどこにあるのかを「追跡」しなければならないことと関係があると思います。 –
確かに - 私は自分の質問にコードを追加しました。このように長い時間を要する行は、前述の 'Array.Sort'の呼び出しです。私の理解では、 'Array.Sort'は範囲の開始に基づいてCCをソートするためにcomparerを使います。ドキュメントにCCが十分にあると突然「Range.Start」にアクセスするのが非常に遅くなってしまっているのですが、あらかじめそれらを反復処理することでスピードアップできる理由は分かりません。私の貧しい脳には非常に混乱しています! – Zout