2011-09-15 5 views
2

オブジェクト値に基づいて更新されているXMLコードがあります。ここでの 'foreach'ループは、200kbのxmlファイルを取得するためにほぼ12-15分かかります。パフォーマンスをどのように向上させるかをお勧めします。私はより良いアプローチは、C#クラスにXMLをデシリアライズすることだと思うオブジェクトにLinqのパフォーマンスの問題がより多くの時間を取る

IEnumerable<XElement> elements = xmlDoc.Descendants(); 
foreach (DataSource Data in DataLst) 
{ 
    XElement xmlElem = (from xmlData in elements 
         where Data.Name == xmlData.Name.LocalName //Name 
          && Data.Store == xmlData.Element(XName.Get("Store", "")).Value 
          && Data.Section == xmlData.Element(XName.Get("Section", "")).Value 
         select xmlData.Element(XName.Get("Val", ""))).Single(); 

    xmlElem.ReplaceWith(new XElement(XName.Get("Val", ""), Data.Value)); 
} 
+0

xmlData.Element(XName.Get( "XYZ"、 "")) 'はxmlData.Element(" XYZ ")' 。はるかに読みやすい。 –

+0

これは、すべてのファイルを*フェッチするものではありません。しかしタイミングは非常に奇妙なように思えます。短くて完全なプログラムでこれを再現できますか? (わかりやすくするために、単に 'XName.Get'ではなく' XName'に文字列変換を使用するだけです。) –

答えて

1

コード(xmlファイルは、子(レベル4)タグの数は、それぞれ10である4個の平準化タグで構成されて)それでLINQを使うと、速くなるはずです。

0

それは本当にこれを実行するには、この長い時間がかかる場合は、多分このような何か:

  1. は両方の反復はいけない - だけでXML-ファイルを反復処理し、SQLを作る(あなたDataLstからデータをロードします(Name/Store/Sectionに基づいてデータをロードするためのコマンドや単純なlinq文)、このデータ(Name/Store/Section)を使用してキーのシンプルな構造体/クラスを作成する - equalsを実装することを忘れないでください。GetHashCode
  2. あなたのXML要素を繰り返し処理し、置換する値を見つけるために辞書を使用してください。

この方法では、DataSource内のすべてのデータに対してXMLファイルを1回だけ反復処理します。

2

ここでO(n)× O(m)の問題があります。n = DataListのサイズ、m = xmlのサイズです。このO(n)+ O(m)を作成するには、データのインデックスを作成する必要があります。例えば:

var lookup = elements.ToLookup(
     x => new { 
      Name = x.Name.LocalName, 
      Store = x.Element(XName.Get("Store", "")).Value, 
      Section = x.Element(XName.Get("Section", "")).Value}, 
     x => x.Element(XName.Get("Val", "")) 
    ); 

foreach (DataSource Data in DataLst) 
{ 
    XElement xmlElem = lookup[ 
      new {Data.Name, Data.Store, Data.Section}].Single(); 
    xmlElem.ReplaceWith(new XElement(XName.Get("Val", ""), Data.Value)); 
} 

ことが非常に長い時間だ - - それは長いことを取っている理由

+0

これは私がとるアプローチです。私は、このアプローチが完了するまでに15秒以下かかると推測しています。 – Enigmativity

0

それははっきりしていない(未テストは、一般的なアプローチだけを表示します)。 DataLstにはいくつの要素がありますか?

IEnumerable<XElement> elements = xmlDoc.Descendants(); 
foreach (DataSource data in DataLst) 
{ 
    XElement valElement = (from element in xmlDoc.Descendants(data.Name) 
          where data.Store == element.Element("Store").Value 
           && data.Section == element.Element("Section").Value 
          select element.Element("Val")).Single(); 

    valElement.ReplaceWith(new XElement("Val"), data.Value)); 
} 

(私は方法によって、実際に名前空間を持ってあなたの要素のどれを想定していないよ)

次はアップ::を置き換えることを検討シンプルさががで開始するために私は、クエリを書き換えます要素自体を置き換える代わりにvalElementとします。それを変更します。それは、それが長いこれを取るべきではありませんように聞こえるので、今

valElement.ReplaceAll(data.Value); 

、これがすべてでは...など事前計算を回避するためのシンプルさに維持しようとしてきました。しかし、は、MarcとCarstenの提案のようにルックアップを構築する必要があります。

+0

宣言は次のとおりです。private IEnumerable DataLst = null; DataLstにはほぼ316の要素があります。 – spins3

+0

@ spins3:これは、長い時間がかかる場合にいくつのアイテムがあるかを調べるのに役立ちません。 –

+0

316個の要素があります。 – spins3

0

Single()First()と置き換えてみてください。

0

炎の危険性があるので、代わりにXQueryでこれを記述することを考えましたか?まともなXQueryプロセッサがこのクエリを効率的に処理する結合オプティマイザを持つ可能性は非常に高いです。

0

「まあおかげであなたの貴重な時間と労力のために、誰も」

問題の答え:私はそれを変更した後、実際にオブジェクトのDataLstは、 "値を得ることに時間を割いた< IEnumerableをタイプ>であったが、リスト<>パフォーマンスを大幅に改善しました(現在20秒で実行中)

関連する問題