【问题标题】:c# Code optimization for large volume of datac#大数据量的代码优化
【发布时间】:2018-05-31 16:15:54
【问题描述】:

我正在通过 TCP 获取大量数据。数据中有 2 种类型的 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 时间。

我想进一步优化代码。欢迎提出任何建议。

提前致谢。

【问题讨论】:

  • 您可以并行化您的代码,以便并行处理 xml。
  • 您可以尝试使用StringBuilder.ToString(int startIndex, int length) 函数仅转换字符串的一部分(例如前105个字符或后50个字符)。那么操作应该至少快一点。
  • 显示,如何声明和填写sb
  • 不要多次调用sb.ToString(),从块中构造字符串是昂贵的。使用基于数组的缓冲区而不是 StringBuilderList 也可能有所帮助(检查性能以确认)。
  • 您可以使用循环和索引器 (sb[i]) 检查字符串生成器是否以某个字符串结尾,完全避免使用ToString

标签: c# string optimization cpu-usage


【解决方案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
}

【讨论】:

  • 我尝试了不同的数据结构,现在使用 List 并且效果很好。
  • 很高兴知道(尽管内部 StringBuilder 也是字符列表)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多