C#正则表达式性能纯相对JS
Posted
技术标签:
【中文标题】C#正则表达式性能纯相对JS【英文标题】:C# Regex performance pure relative JS 【发布时间】:2018-05-30 14:52:52 【问题描述】:我对@987654321@的正则表达式速度有很好的体验。
我决定做一个小比较。我运行了以下代码:
var str = "A regular expression is a pattern that the regular expression engine attempts to match in input text.";
var re = new RegExp("t", "g");
console.time();
for(var i = 0; i < 10e6; i++)
str.replace(re, "1");
console.timeEnd();
结果:3888.731ms。
现在在C#
:
var stopwatch = new Stopwatch();
var str = "A regular expression is a pattern that the regular expression engine attempts to match in input text.";
var re = new Regex("t", RegexOptions.Compiled);
stopwatch.Start();
for (int i = 0; i < 10e6; i++)
re.Replace(str, "1");
stopwatch.Stop();
Console.WriteLine( stopwatch.Elapsed.TotalMilliseconds);
结果:32798.8756ms !!
现在,我尝试了re.exec(str);
vs Regex.Match(str, "t");
:1205.791ms VS 7352.532ms 支持JS
。
在.net
做海量文字处理“不适合”吗?
使用 [ta]
模式(而不是 t
文字)更新 1 个相同的测试:
3336.063ms in js VS 64534.4766!!! in c#.
另一个例子:
console.time();
var str = "A regular expression is a pattern that the regular expression engine attempts 123 to match in input text.";
var re = new RegExp("\\d+", "g");
var result;
for(var i = 0; i < 10e6; i++)
result = str.replace(str, "$0");
console.timeEnd();
js 中的 3350.230ms,c# 中的 32582.405ms。
【问题讨论】:
你试过c#中的预编译正则表达式吗? 我能够重现 c# 性能,Release/Any CPU (64 bit)/Not Running in Visual Studio。我使用 RegexOptions.None 的时间:46509.2514 毫秒。我使用 RegexOptions.Compiled 的时间:36174.9981 毫秒。 分配 str.replace(re, "1");以确保 JS 不会将其视为无操作并对其进行优化 @AlexK。result = str.replace(str, "1");
= 3026.953ms
好的,但是,我不明白为什么更新 2 测试“更有用”。顺便说一句,当您在 RegExp
构造函数的双引号字符串中写入 \d+
时,它被解释为 d+
(无意义的转义被简单地忽略,下一个字符被视为文字)。要在双引号字符串中计算\d
字符类,您必须使用两个反斜杠:var re=RegExp("\\d+", "g");
。注意写var re=/\d+/g;
或var re=RegExp(/\d+/g);
是完全一样的(这些版本都不是更早或更晚编译的。)
【参考方案1】:
String
在 C# 中是一个危险的野兽,如果你不小心使用它,你真的可以在脚下开枪,但我认为给定的测试没有足够的代表性来保证任何概括。
首先,我确实为您的测试用例重现了类似的性能。添加 RegexOptions.Compiled
将所需时间减少到 30 秒左右,但这仍然是显着的差异。
具体的测试用例可能不太现实,谁会使用正则表达式进行单个字符替换? 如果您为此任务使用专用 API,您将获得可比较的结果 str.Replace('t', '1');
在我的机器上是 1600 毫秒。
这意味着对于这个特定任务,C# 的性能与 JS 相当。 C#Regex.Replace()
在内部是否不适合单字符替换,或者 JS 正则表达式版本是否正在优化正则表达式 - 一些 JS 大师应该回答这个问题。
更现实的复杂正则表达式是否会有显着差异 - 知道会很有趣。
编辑: 我验证了当实际使用替换结果以及每次运行中输入字符串不同时(我的测试中为 10 秒与 35 秒),性能差距仍然存在。所以差距较小,但仍然存在。
可能的原因
根据this SO question 浏览器实现的提示,将一些字符串操作委托给优化的 c++ 代码。如果他们对字符串 concat 执行此操作,他们可能也会对 Regex 执行此操作。 AFAIK、C# Regex 和 String 类留在托管世界中,这带来了一些包袱。
【讨论】:
在字符串中添加一个数字,并将表达式更改为\d+
。我认为这是一个有用的经典案例。结果相似(4 秒对 31 秒)。【参考方案2】:
JS regex 和 .NET regex 有很大区别的一个原因是 JS 缺乏相当多的高级功能,但是 .NET 功能非常丰富。
这是来自regular-expressions.info
的两句话:
JavaScript 实现 Perl 风格的正则表达式。然而,它 缺少 Perl 和其他软件中可用的大量高级功能 现代正则表达式风格:
没有 \A 或 \Z 锚来匹配字符串的开头或结尾。用一个 插入符号或美元。
没有原子分组或所有格量词。
不支持 Unicode,除了用 \uFFFF 匹配单个字符。
没有命名的捕获组。改为使用编号的捕获组。
没有模式修饰符可以在正则表达式中设置匹配选项。
没有条件。
没有正则表达式 cmets。描述你的常客 用 JavaScript // cmets 代替表达式,在常规之外 表达式字符串。
.NET Framework:
Microsoft .NET Framework,可与任何 .NET 一起使用 编程语言,例如 C# (C sharp) 或 Visual Basic.NET,具有 对正则表达式的可靠支持。 .NET 的正则表达式风格非常 功能丰富。缺少的唯一值得注意的功能是 所有格量词。
【讨论】:
以上是关于C#正则表达式性能纯相对JS的主要内容,如果未能解决你的问题,请参考以下文章
实例JS 正则表达式提取 html 中纯文本,去掉样式,其它标签