【问题标题】:large string data parsing causing high-cpu usage大字符串数据解析导致高 CPU 使用率
【发布时间】:2023-03-07 08:19:01
【问题描述】:

我的应用程序需要解析一些大字符串数据。这意味着我大量使用字符串类的 Split、IndexOf 和 SubString 方法。我正在尝试在必须进行任何连接的任何地方使用 StringBuilder 类。但是,当应用程序执行此解析时,应用程序 cpu 使用率会很高(60-70%)。我猜想调用这些字符串 API 是导致 CPU 使用率升高的原因,特别是数据的大小很大(字符串的典型长度为 400K)。有什么想法可以验证是什么导致 cpu 使用率如此之高,以及是否有任何关于如何降低 cpu 使用率的建议?

【问题讨论】:

  • 您没有具体说明为什么高 CPU 使用率是一件坏事。您是否试图为其他进程/线程留出足够的“喘息空间”?
  • 分析它并寻找瓶颈。确定不是 IO 操作(读/写磁盘)引起的吗?
  • @Vlad。一般来说,您不希望控制 cpu 的使用吗?当高 CPU 使用率被认为是一件好事?
  • 字符串解析总是产生 100% 的 cpu 使用率,你要求它做真正的工作。找出您损失 40-30% 的原因应该是您关心的问题。可能是 I/O,读/写文件数据。您对此无能为力,但在另一个线程中执行此操作以便您可以将其与解析重叠会有所帮助。很难达到 100%。
  • @palm-snow 定义“在控制之下”。它以 100% 运行的事实意味着它不必等待内存和/或 I/O。因此,这意味着它现在正在执行您要求它执行的操作,而不是稍后执行。我认为这是一件好事。就像@Hans Passant 提到的,实现 100% 通常是一个目标,而不是问题。

标签: c# string


【解决方案1】:

要检查的一件事是您尽可能多地传递 StringBuilder,而不是创建一个新的,然后不必要地返回它的 ToString()。

如果您将数据处理为较小的字符串,从流中读取,则可以获得更大的收益。当然,这取决于您正在执行哪种操作,但如果可能的话,请从 StreamReader(或类似的,取决于源)中读取小块数据,然后将其写入 StreamWriter。

通常更改仅适用于给定的文本行,这使得以下模式立即有用:

using(StreamReader sr = new StreamReader(sourceInfo))
using(StreamWriter sw = new StreamWriter(destInfo))
  for(string line = sr.ReadLine(); line != null; line = sr.ReadLine())
    sw.WriteLine(ManipulateString(line));

在其他不适用的情况下,仍有办法将要处理的字符串分块。

【讨论】:

    【解决方案2】:

    要了解 CPU 使用率的来源:请参阅 What Are Some Good .NET Profilers?

    降低 CPU 使用率:当然,这取决于实际花费的时间。例如,您可能会考虑不使用实际的子字符串,而是使用小对象编码它们在它们来自的大字符串中的位置。 (不能保证这实际上是一种改进。)很有可能,当你分析你的代码时,有一些事情会作为问题跳出来。它们很可能是您从未猜到的东西,一旦您知道它们需要修复,它们可能很容易修复。

    【讨论】:

      【解决方案3】:

      如果您的解析器不需要进行回溯,即它总是向前读取字符串并且字符串的源不是您可以使用的文件/网络流StreamReader只需将您的字符串包装在StringReader 中,例如

      //Create a StringReader using the String variable data which has your String in it
      //A StringReader is just a TextReader implementation for Strings
      StringReader reader = new StringReader(data);
      
      //Now do whatever manipulation on the string you want...
      

      【讨论】:

      • +1 是的,这可以提供帮助,如果字符串根本无法从流中获取,那么值得一试。但是,如果字符串是从流中获取的(甚至是间接的,例如最终来自 Request.InputStream 并为您完成一些处理的大量 Request.Form 值),那么直接从流中获取它可能是一个很大的收获.
      • 是的,我写了很多流解析器,尤其是在过去一两年里,我总是尽可能地尝试使用StreamReader
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2017-10-09
      • 2013-02-12
      相关资源
      最近更新 更多