是否有人围绕StringBuilders或Streams实现了正则表达式和/或Xml解析器?

我正在建立一个压力测试客户端,它使用尽可能多的线程来锤击服务器并分析响应,客户可以集合。 我经常发现自己受到垃圾收集(和/或缺少垃圾收集)的限制,并且在大多数情况下,它归结为我实例化的字符串,只是将它们传递给Regex或Xml解析例程。

如果你反编译Regex类,你会在内部看到它使用StringBuilders来做几乎所有事情,但你不能传递给字符串构建器; 在开始使用私有方法之前,它有助于深入研究私有方法,因此扩展方法也不会解决它。 如果您想从System.Xml.Linq中的解析器中获取对象图,则处于类似情况。

这不是一个迂腐过度优化的案例。 我查看了StringBuilder问题和其他问题中的正则表达式替换 。 我还分析了我的应用程序以查看天花板的来源,并且使用Regex.Replace()现在确实在方法链中引入了大量开销,我试图以每小时数百万的请求命中服务器并检查错误和嵌入式诊断代码的XML响应。 我已经摆脱了限制吞吐量的所有其他低效率,并且当我不需要捕获组或反向引用时,我甚至通过扩展StringBuilder来进行通配符查找/替换,从而减少了大量的Regex开销。但在我看来,现在有人会自己包装一个自定义的StringBuilder(或更好的,基于Stream)的Regex和Xml解析实用程序。

好吧,如此咆哮,但我自己必须这样做吗?

更新:我找到了一个解决方法,将峰值内存消耗从几千兆字节降低到几百兆,所以我将其发布在下面。 我不是把它作为答案添加因为a)我一般不喜欢这样做,而且b)我仍然想知道是否有人花时间定制StringBuilder来做Regexes(或反之亦然)。

在我的情况下,我无法使用XmlReader,因为我正在摄取的流包含某些元素中的一些无效二进制内容。 为了解析XML,我必须清空这些元素。 我以前使用单个静态编译的Regex实例来进行替换,这就像疯了一样消耗内存(我正在尝试处理~300个10KB docs / sec)。 大幅减少消费的变化是:

  1. 我在CodeProject上的这篇StringBuilder Extensions文章中添加了代码,用于方便的IndexOf方法。
  2. 我添加了一个(非常)原始的WildcardReplace方法,允许每次调用一个通配符(*或?)
  3. 我用WildcardReplace()调用替换了正则表达式用法,以清空有问题的元素的内容

这是非常不合适的,仅在我自己的目的要求下进行测试; 我会让它更优雅和强大,但YAGNI和所有这一切,我很匆忙。 这是代码:

 ///  /// Performs basic wildcard find and replace on a string builder, observing one of two /// wildcard characters: * matches any number of characters, or ? matches a single character. /// Operates on only one wildcard per invocation; 2 or more wildcards in  /// will cause an exception. /// All characters in  are treated as literal parts of /// the replacement text. ///  ///  ///  ///  public static StringBuilder WildcardReplace(this StringBuilder sb, string find, string replaceWith) { if (find.Split(new char[] { '*' }).Length > 2 || find.Split(new char[] { '?' }).Length > 2 || (find.Contains("*") && find.Contains("?"))) { throw new ArgumentException("Only one wildcard is supported, but more than one was supplied.", "find"); } // are we matching one character, or any number? bool matchOneCharacter = find.Contains("?"); string[] parts = matchOneCharacter ? find.Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries) : find.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries); int startItemIdx; int endItemIdx; int newStartIdx = 0; int length; while ((startItemIdx = sb.IndexOf(parts[0], newStartIdx)) > 0 && (endItemIdx = sb.IndexOf(parts[1], startItemIdx + parts[0].Length)) > 0) { length = (endItemIdx + parts[1].Length) - startItemIdx; newStartIdx = startItemIdx + replaceWith.Length; // With "?" wildcard, find parameter length should equal the length of its match: if (matchOneCharacter && length > find.Length) break; sb.Remove(startItemIdx, length); sb.Insert(startItemIdx, replaceWith); } return sb; } 

XmlReader是一个基于流的XML解析器。 请参阅http://msdn.microsoft.com/en-us/library/756wd7zs.aspx

Mono项目已将其核心库的许可证转换为MIT X11许可证 。 如果您需要在特定应用程序中创建为性能而定制的正则表达式库,您应该能够从Mono的 System库实现中获得最新代码。