2017-12-18 189 views
1

我通过TCP获取大容量数据。数据中有2种类型的XML数据包。我需要尽快处理它。c#大量数据的代码优化

<?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时间。

我想进一步优化代码。任何建议都是值得欢迎的。

在此先感谢。

+0

可以并行代码,以处理XML并行。 – Jepessen

+0

您可以尝试使用'StringBuilder.ToString(int startIndex,int length)'函数仅转换部分字符串_(例如前105个字符或后50个字符)_。那么操作应该至少快一点。 – Julo

+0

显示,你如何声明并填充'sb' – Backs

回答

1

您可以尝试检查字符串生成器是否以给定的字符串结尾并使用循环和索引器,并查看是否可以提高性能。例如:

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 
} 
+0

我尝试了不同的数据结构,现在使用列表和它完美的作品。 – Manjoor

+0

很高兴知道(虽然内部StringBuilder也是字符列表)。 – Evk