C#正则表达式性能纯相对JS

Posted

技术标签:

【中文标题】C#正则表达式性能纯相对JS【英文标题】:C# Regex performance pure relative JS 【发布时间】:2018-05-30 14:52:52 【问题描述】:

我对@9​​87654321@的正则表达式速度有很好的体验。

我决定做一个小比较。我运行了以下代码:

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:

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的主要内容,如果未能解决你的问题,请参考以下文章

C# |正则表达式 |如何提高我的正则表达式性能

js如何正则验证密码

C#正则基础正则表达式

实例JS 正则表达式提取 html 中纯文本,去掉样式,其它标签

实例JS 正则表达式提取 html 中纯文本,去掉样式,其它标签

实例JS 正则表达式提取 html 中纯文本,去掉样式,其它标签