我通过TCP获取大量数据。数据中有两种类型的XML数据包。我需要尽快处理它。
<?xml version="1.0" encoding="UTF-8"?><xsi:Event> .... [dynamic length data] .... </xsi:Event>
和
<?xml version="1.0" encoding="UTF-8"?><ChannelHeartBeat xmlns="http://schema.broadsoft.com/xsi"/>
有时数据包没有xml声明。
这是旧代码。
char c = (char)streamReader.Read();
sb.Append(c);
if(sb.ToString().EndsWith("</xsi:Event>",StringComparison.OrdinalIgnoreCase))
{
....
sb.Clear();
}
if(sb.ToString().EndsWith("<ChannelHeartBeat xmlns=\"http://schema.broadsoft.com/xsi\"/>", StringComparison.OrdinalIgnoreCase))
{
....
sb.Clear();
}
ToString()
在上面的代码中占用了26%的CPU时间。
以下是优化代码。它将性能提升了30%
char c = (char)streamReader.Read();
sb.Append(c);
n++;
if (n > 60)
{
if (c == '>')
{
if (n < 105)
{
string temp = sb.ToString();
if (temp.EndsWith("<ChannelHeartBeat xmlns=\"http://schema.broadsoft.com/xsi\"/>", StringComparison.OrdinalIgnoreCase))
{
sb.Clear();
n = 0;
}
}
if (n > 700)
{
string temp = sb.ToString();
if (temp.EndsWith("</xsi:Event>", StringComparison.OrdinalIgnoreCase))
{
sb.Clear();
n = 0;
}
}
}
}
}
ToString()
现在占用了8%的CPU时间。
我想进一步优化代码。任何建议都是受欢迎的。
提前致谢。
您可以尝试使用循环和索引器检查字符串构建器是否以给定字符串结束,并查看是否可以提高性能。例如:
public static class Extensions {
public static bool EndsWith(this StringBuilder sb, string target, bool caseInsensetive = false) {
// if sb length is less than target string
// it cannot end with it
if (sb.Length < target.Length)
return false;
var offset = sb.Length - target.Length;
for (int i = sb.Length - 1; i >= offset; i--) {
var left = sb[i];
var right = target[i - offset];
// conver to upper-case for insensetive comparision
// if necessary
if (caseInsensetive) {
left = Char.ToUpper(left, CultureInfo.InvariantCulture);
right = Char.ToUpper(right, CultureInfo.InvariantCulture);
}
// fail fast
if (left != right)
return false;
}
return true;
}
}
用法:
const string HeartBeatEnding = "<ChannelHeartBeat xmlns=\"http://schema.broadsoft.com/xsi\"/>";
const string EventEnding = "</xsi:Event>";
char c = (char)streamReader.Read();
sb.Append(c);
if (sb.EndsWith(EventEnding)) {
// do stuff
}
else if (sb.EndsWith(HeartBeatEnding)) {
// do stuff
}