19 .net c# csv string performance
我正在读取CSV文件的每一行,需要获取每列中的各个值.所以现在我只是使用:
values = line.Split(delimiter);
Run Code Online (Sandbox Code Playgroud)
where line是一个字符串,它包含分隔符分隔的值.
测量我的ReadNextRow方法的性能我注意到它花了66%String.Split,所以我想知道是否有人知道更快的方法来做到这一点.
谢谢!
Joh*_*ren 21
string.Split的BCL实现实际上非常快,我在这里做了一些测试,试图预先形成它并不容易.
但是有一件事你可以做,那就是将它作为一个生成器来实现:
public static IEnumerable<string> GetSplit( this string s, char c )
{
int l = s.Length;
int i = 0, j = s.IndexOf( c, 0, l );
if ( j == -1 ) // No such substring
{
yield return s; // Return original and break
yield break;
}
while ( j != -1 )
{
if ( j - i > 0 ) // Non empty?
{
yield return s.Substring( i, j - i ); // Return non-empty match
}
i = j + 1;
j = s.IndexOf( c, i, l - i );
}
if ( i < l ) // Has remainder?
{
yield return s.Substring( i, l - i ); // Return remaining trail
}
}
Run Code Online (Sandbox Code Playgroud)
对于小字符串,上面的方法不一定比string.Split更快,但它会在找到它们时返回结果,这是懒惰评估的强大功能.如果你排长队或需要节省内存,这就是你要走的路.
上面的方法受到IndexOf和Substring的性能的限制,它执行过多的范围检查索引,并且需要更快地优化它们并实现自己的辅助方法.你可以击败string.Split性能,但它会采取切割器int-hacking.你可以在这里阅读我的帖子.
cle*_*tus 18
应该指出的split()是,如果您在文件中遇到逗号,则解析CSV文件是一种可疑的方法,例如:
1,"Something, with a comma",2,3
Run Code Online (Sandbox Code Playgroud)
在不知道你如何分析的情况下,我要指出的另一件事是小心分析这种低级细节.Windows/PC计时器的粒度可能会发挥作用,您可能在循环中有很大的开销,因此使用某种控制值.
话虽这么说,它split()是为处理正则表达式而构建的,这些正则表达式显然比你需要的更复杂(而且无论如何都是处理转义逗号的错误工具).此外,split()还会创建大量临时对象.
因此,如果你想加快它(我很难相信这部分的性能确实是一个问题)那么你想要手工完成它并且你想重用你的缓冲区对象,所以你不是经常创建对象和给予垃圾收集器的工作是清理它们.
该算法相对简单:
哦,为了让你对正则表达式的成本有所了解,有一个问题(Java不是C#,但原理是相同的),有人想用字符串替换每个第n个字符.我建议replaceAll()在String上使用.Jon Skeet手动编码循环.出于好奇,我对两个版本进行了比较,他的数量提高了一个数量级.
所以,如果你真的想要表现,那就是时候解析了.
或者,更好的是,使用其他人的优化解决方案,如快速CSV阅读器.
顺便说一句,虽然这与Java有关,但它涉及正则表达式(通用)和replaceAll()手动编码循环的性能:将char放入每个N个字符的java字符串中.
这是一个使用 ReadOnlySpan 的非常基本的示例。在我的机器上,这大约需要 150 纳秒,而 string.Split() 大约需要 250 纳秒。40% 的改进就已经很不错了。
string serialized = "1577836800;1000;1";
ReadOnlySpan<char> span = serialized.AsSpan();
Trade result = new Trade();
index = span.IndexOf(';');
result.UnixTimestamp = long.Parse(span.Slice(0, index));
span = span.Slice(index + 1);
index = span.IndexOf(';');
result.Price = float.Parse(span.Slice(0, index));
span = span.Slice(index + 1);
index = span.IndexOf(';');
result.Quantity = float.Parse(span.Slice(0, index));
return result;
Run Code Online (Sandbox Code Playgroud)
请注意,ReadOnlySpan.Split() 很快将成为框架的一部分。请参阅 https://github.com/dotnet/runtime/pull/295
| 归档时间: |
|
| 查看次数: |
27620 次 |
| 最近记录: |