Reputation: 3168
We have got an XMLIDList helper which uses += ( :( )
What I am looking for, what is the fastest possible way to do this? It is not been a problem before because the lists have been <10 items, but we have added a new feature that can pass 15k items. And as you can imagine, it is slow.
public static string EncodeGuidListToXML(IList<Guid> elementsToEncode)
{
if (elementsToEncode == null || elementsToEncode.Count == 0)
return String.Empty;
string beginItemNode = BeginItemNode;
string endItemNode = EndItemNode;
string xml = BeginRootNode;
foreach (Guid item in elementsToEncode)
{
xml += beginItemNode + item.ToString().ToUpper() + endItemNode;
}
xml += EndRootNode;
return xml;
}
Upvotes: 3
Views: 1211
Reputation: 16974
I ran a few test using your standard string method, the StringBuilder class method and a method utilising the XDocument and XElement classes. With short lists the StringBuilder class won but with larger lists the XML classes gave comparable times. The test code I used is below:
List<string> list;
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
protected void Page_Load(object sender, EventArgs e)
{
list = Enumerable.Range(0, 15000).Select(i => i.ToString()).ToList();
UsingStrings();
UsingStringBuilder();
UsingXDocument();
}
private void UsingStrings()
{
timer.Reset();
timer.Start();
string beginItemNode = "<Node>";
string endItemNode = "</Node>";
string xml = "<Root>";
foreach (string item in list)
{
xml += beginItemNode + item + endItemNode;
}
xml += "</Root>";
timer.Stop();
Response.Write(string.Format("Strings time:{0}<br />", timer.Elapsed.Ticks));
}
private void UsingStringBuilder()
{
timer.Reset();
timer.Start();
StringBuilder sb = new StringBuilder();
sb.Append("<Root>");
foreach (string item in list)
{
sb.AppendFormat("<Node>{0}</Node>", item);
}
sb.Append("</Root>");
timer.Stop();
Response.Write(string.Format("StringBuilder time:{0}<br />", timer.Elapsed.Ticks));
}
private void UsingXDocument()
{
timer.Reset();
timer.Start();
XDocument xDoc = new XDocument();
xDoc.Add(new XElement("Root"));
foreach (var item in list)
{
XElement element = new XElement("Node", item);
xDoc.Root.Add(element);
}
timer.Stop();
Response.Write(string.Format("XDocument time:{0}<br />", timer.Elapsed.Ticks));
}
The above test gave the following results on my machine:
First run:
Strings time:239750613
StringBuilder time:55509
XDocument time:61904
Second run:
Strings time:289422753
StringBuilder time:198595
XDocument time:80032
If you want to display the XDocument XML as a string without formatting use:
string xml = xDoc.ToString(SaveOptions.DisableFormatting);
EDIT: I initially said XDocument was much faster but running the test a few times it seems that it is generally equivalent to the StringBuilder method although it appears to be more consistent whereas sometimes StringBuilder is faster, other times a fair bit slower. What is clear is that using strings is much slower in comparison.
Upvotes: 3
Reputation: 1500495
The best way is not to use string concatenation to start with, IMO. Use an XML API. Build an XDocument
or an XmlDocument
, and then convert that to a string at the end. While your logic is reasonably simple at the moment, as soon as you start needing values which need escaping or anything like that, you really don't want to be replicating all the logic of a real XML API... so use an existing one.
Here's an example of how you might rewrite your current method:
public static string EncodeGuidListToXml(IList<Guid> guids)
{
if (elementsToEncode == null || elementsToEncode.Count == 0)
{
return "";
}
return new XDocument(
new XElement("Root",
guids.Select(guid => new XElement("Item", guid.ToString().ToUpper()))
)).ToString();
}
If you really want to stick to building strings directly, StringBuilder
is indeed the way to go.
Upvotes: 4
Reputation: 137148
Using a StringBuilder
should give you some performance improvements.
Because it "represents a mutable string of characters" it's much faster at string manipulation than concatenating strings directly as it doesn't have to copy the string each time
Upvotes: 7