【问题标题】:Is it faster to access char in string via [] operator or faster to access char in char[] via [] operator?通过 [] 运算符访问字符串中的 char 更快还是通过 [] 运算符访问 char[] 中的 char 更快?
【发布时间】:2012-11-01 14:48:14
【问题描述】:

我有一个简单的问题。我正在使用 C# 中的一个巨大的 string 工作,并且我反复浏览它并通过 [] 运算符访问单个字符。将string 转换为char[] 并在char 数组上使用[] 运算符更快还是我的方法更快?还是两者都一样?我希望我的程序能够快速领先。

【问题讨论】:

  • 你自己测试过吗?您是否有任何证据表明索引是您工作量的重要组成部分?看来您比我们更适合进行适当的测试。
  • 它们都是一样的......出于任何实际目的
  • 你为什么不做两个应用程序。测试这两种方法,看看哪一种最快?如果差异不明显,请尝试执行 1000 次。

标签: c# string performance


【解决方案1】:

如果您需要绝对最快实现,那么您可以转到unsafe 并使用指针:

string s = ...
int len = s.Length;
fixed (char* ptr = s)
{
   // talk to ptr[0] etc; DO NOT go outside of ptr[0] <---> ptr[len-1]
}

然后避免范围检查但是

  • 需要unsafe
  • 如果你越界了,你会受到责备

【讨论】:

  • 我知道这是旧的,但我对此有疑问。将s 包装在Span&lt;T&gt; 中并使用它的索引运算符会比使用string 的索引运算符更快吗?
  • @Andy 这是一个最好通过 benchmarkdotnet 之类的问题来回答的问题 - 我怀疑这将是上下文相关的:对于随机访问,我怀疑“可能不会”;但是,如果您要在跨度上使用foreachfor(int i = 0 ; i &lt; span.Length ; i++) 循环检查每个字符,那么:省略跨度的JIT 边界可能会使其更快。它还取决于您正在谈论的框架:JIT 边界删除 span 仅适用于 .NET Core 3.1(或可能 3.0)及更高版本
【解决方案2】:

首先:你应该测量。没有人可以在不衡量的情况下明确回答这个问题。

在这种特殊情况下,一切都表明直接访问string 更好:字符串在几乎所有语言中都被实现为字符数组,并且手动将字符串转换为char[] 需要立即分配另一个巨大的内存量。这可不好。

但我不会相信我自己的话。 测量

【讨论】:

    【解决方案3】:

    string 转换为char[] 的一个明显缺点是需要复制:由于 C# 中的字符串是不可变而数组是可变,因此您的代码将最终复制了整个巨大的字符串!这几乎肯定会使转换后的潜在速度提升(如果有的话)相形见绌。

    【讨论】:

    • 2021 年不再是这种情况了,我们有ReadOnlySpan&lt;char&gt;
    【解决方案4】:

    string 底层的 char[] 数组。所以从字面上看没有区别。

    这里更大的问题是,尝试在堆栈的最底层进行优化可能是浪费时间,其他地方可能还有更好的改进。

    【讨论】:

    • 实际上,不是;它是一个char* 对它自己,并且它本身的大小是可变的。
    • 其次,数组访问 (ldelem*) 和索引器访问 (callvirt) 之间存在差异 - C# 语法相同,但它们是不同的实现。
    • 另请注意,如果索引器对两者都相同,那么您需要努力复制字符串以将其转换为 char 数组,这需要付出代价。 char[] 需要明显更快才能成为净收益。
    • 有趣。每天学习新东西!
    • .NET 中只有两种类型具有可变大小(每个实例,我的意思是——一旦分配就不会改变):数组和String(编辑:和Utf8String in .NET 5)
    猜你喜欢
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    相关资源
    最近更新 更多