我正在将一些带有多个string
字段的记录从旧数据库导入到新数据库。它看起来很慢,我怀疑这是因为我这样做:
foreach (var oldObj in oldDB)
{
NewObject newObj = new NewObject();
newObj.Name = oldObj.Name.Trim().Replace('^', 'Č').Replace('@', 'Ž').Replace('[', 'Š')
.Replace(']', 'Ć').Replace('`', 'ž').Replace('}', 'ć')
.Replace('~', 'č').Replace('{', 'š').Replace('\\', 'Đ');
newObj.Surname = oldObj.Surname.Trim().Replace('^', 'Č').Replace('@', 'Ž').Replace('[', 'Š')
.Replace(']', 'Ć').Replace('`', 'ž').Replace('}', 'ć')
.Replace('~', 'č').Replace('{', 'š').Replace('\\', 'Đ');
newObj.Address = oldObj.Address.Trim().Replace('^', 'Č').Replace('@', 'Ž').Replace('[', 'Š')
.Replace(']', 'Ć').Replace('`', 'ž').Replace('}', 'ć')
.Replace('~', 'č').Replace('{', 'š').Replace('\\', 'Đ');
newObj.Note = oldObj.Note.Trim().Replace('^', 'Č').Replace('@', 'Ž').Replace('[', 'Š')
.Replace(']', 'Ć').Replace('`', 'ž').Replace('}', 'ć')
.Replace('~', 'č').Replace('{', 'š').Replace('\\', 'Đ');
/*
... some processing ...
*/
}
字符串
现在,我通过网络阅读了一些帖子和文章,在那里我看到了许多关于这一点的不同想法。有些人说如果我用MatchEvaluator
来做正则表达式会更好,有些人说最好让它保持原样。
虽然我自己做一个基准案例可能会更容易,但我决定在这里问一个问题,以防其他人也想知道同样的问题,或者有人提前知道。
那么在C#中最快的方法是什么呢?
- 编辑 *
我在这里发布了基准。乍一看,理查德的方法可能是最快的。然而,他的方式,也不是Marc的方式,会因为错误的Regex模式而做任何事情。在将图案从
@"\^@\[\]`\}~\{\\"
型
至
@"\^|@|\[|\]|`|\}|~|\{|\\"
型
看起来好像chained.Replace()调用的老方法是最快的
8条答案
按热度按时间xxe27gdn1#
谢谢你们的输入。我写了一个快速和肮脏的基准测试你的输入。我已经测试了解析4个字符串,迭代了500.000次,并完成了4遍。结果如下:
字符串
这个基准的代码如下。请检查代码并确认@Richard得到了最快的方法。请注意,我没有检查输出是否正确,我假设它们是正确的。
型
编辑2020年6月
由于这个Q&A仍然有点击率,我想用来自user 1664043的额外输入更新它,使用StringBuilder w/ IndexOfAny,这次使用.NET Core 3.1编译,下面是结果:
型
更新的代码:
型
a14dhokn2#
最快的方法
唯一的办法就是自己去比较性能。试着像在Q中一样,使用
StringBuilder
和Regex.Replace
。但是微基准测试没有考虑整个系统的范围。如果这种方法只是整个系统的一小部分,那么它的性能可能对整个应用程序的性能没有影响。
一些注解:
1.如上所述使用
String
(我假设)将创建大量中间字符串:给GC更多的工作。但这很简单。1.使用
StringBuilder
允许在每次替换时修改相同的底层数据。这会产生更少的垃圾。它几乎和使用String
一样简单。1.使用
regex
是最复杂的(因为您需要代码来完成替换),但允许使用单个表达式。我希望这会更慢,除非替换列表非常大,并且在输入字符串中很少有替换(即。大多数replace方法调用不替换任何东西,只是在字符串中进行一次搜索)。我希望#2在重复使用(数千次)时会稍微快一点,因为GC负载更少。
对于正则表达式方法,您需要类似于:
字符串
这可以通过使用
Dictionary<char,char>
参数化以可重用的方式完成,以保存替换和可重用的MatchEvaluator
。v9tzhpje3#
试试这个:
字符串
eoigrqb64#
一个可能的解决方案是使用
StringBuilder
类。可以先将代码重构为单个方法
字符串
3duebb1j5#
你可以在char map上使用lambda表达式Aggregate:
字符串
您可以按如下方式运行此命令:
型
9lowa7mx6#
我会尝试做一些类似的事情:
字符串
这有一个单独的地方需要维护(在顶部),并构建一个预编译的
Regex
来处理替换。所有的开销都是一次完成的(因此是static
)。b1zrtrql7#
使用IndexOfAny的混合StringBuilder方法:
字符串
cgvd09ve8#
从.NET Core 2.1开始,使用
string.Create
和switch
语句可能是最快的方法。字符串
从我的基准测试来看,与使用临时
char[]
、RegEx
和StringBuilder.Replace
相比,速度最快,是4到10倍。上述方法的主要优点是1.通过使用
string.Create
,不需要临时缓冲区。Span.CopyTo
将被框架优化1.循环通过缓冲区只有一次,并直接访问
Span
。1.没有额外的GC分配。