XName オブジェクトの事前アトミック化 (LINQ to XML)
LINQ to XML でパフォーマンスを向上させる方法の 1 つは、XName オブジェクトの事前アトミック化です。 事前アトミック化とは、XElement クラスと XAttribute クラスのコンストラクターを使用して XML ツリーを作成する前に、文字列を XName オブジェクトに割り当てる操作です。 次に、(文字列から XName への暗黙的な変換を使用する) コンストラクターに文字列を渡す代わりに、初期化された XName オブジェクトを渡します。
これによって、特定の名前が繰り返される大きい XML ツリーを作成するときにパフォーマンスが向上します。 これを行うには、XML ツリーを構築する前に、XName オブジェクトを宣言して初期化し、次に要素名と属性名に文字列を指定する代わりに XName オブジェクトを使用します。 この手法では、同じ名前の多数の要素や属性を作成する場合に、パフォーマンスが大幅に向上します。
各自のシナリオで事前アトミック化をテストし、使用すべきかどうかを判断してください。
例
次にコード例を示します。
XName Root = "Root";
XName Data = "Data";
XName ID = "ID";
XElement root = new XElement(Root,
new XElement(Data,
new XAttribute(ID, "1"),
"4,100,000"),
new XElement(Data,
new XAttribute(ID, "2"),
"3,700,000"),
new XElement(Data,
new XAttribute(ID, "3"),
"1,150,000")
);
Console.WriteLine(root);
この例では次の出力が生成されます。
<Root>
<Data ID="1">4,100,000</Data>
<Data ID="2">3,700,000</Data>
<Data ID="3">1,150,000</Data>
</Root>
次の例は同じ手法を示し、XML ドキュメントが名前空間にあります。
XNamespace aw = "https://www.adventure-works.com";
XName Root = aw + "Root";
XName Data = aw + "Data";
XName ID = "ID";
XElement root = new XElement(Root,
new XAttribute(XNamespace.Xmlns + "aw", aw),
new XElement(Data,
new XAttribute(ID, "1"),
"4,100,000"),
new XElement(Data,
new XAttribute(ID, "2"),
"3,700,000"),
new XElement(Data,
new XAttribute(ID, "3"),
"1,150,000")
);
Console.WriteLine(root);
この例では次の出力が生成されます。
<aw:Root xmlns:aw="https://www.adventure-works.com">
<aw:Data ID="1">4,100,000</aw:Data>
<aw:Data ID="2">3,700,000</aw:Data>
<aw:Data ID="3">1,150,000</aw:Data>
</aw:Root>
次に示すのは、より実働環境に近い例です。 この例では、要素の内容がクエリによって提供されます。
XName Root = "Root";
XName Data = "Data";
XName ID = "ID";
DateTime t1 = DateTime.Now;
XElement root = new XElement(Root,
from i in System.Linq.Enumerable.Range(1, 100000)
select new XElement(Data,
new XAttribute(ID, i),
i * 5)
);
DateTime t2 = DateTime.Now;
Console.WriteLine("Time to construct:{0}", t2 - t1);
前の例では、名前が事前アトミック化されていない次の例に比べて良いパフォーマンスが得られます。
DateTime t1 = DateTime.Now;
XElement root = new XElement("Root",
from i in System.Linq.Enumerable.Range(1, 100000)
select new XElement("Data",
new XAttribute("ID", i),
i * 5)
);
DateTime t2 = DateTime.Now;
Console.WriteLine("Time to construct:{0}", t2 - t1);