以下是我可以创建的用于反转字符串
的最快代码public static void ReverseFast(string x)
{
string text = x;
StringBuilder reverse = new StringBuilder();
for (int i = text.Length - 1; i >= 0; i--)
{
reverse.Append(text[i]);
}
Console.WriteLine(reverse);
}
我想解决这个等式中的每个瓶颈,使其尽可能快。到目前为止我唯一能找到的是阵列边界检查,我只是部分理解。无论如何都要禁用它,因为我理解它如果你使用.Length
编译器决定不检查边界但是如果你正在递减,因为我在for
循环中它仍然进行边界检查?有人可以转换为我使用指针避免边界检查,我想测试100k +字符范围内的字符串的速度差异。
根据下面的评论和帖子,这是我到目前为止所提出的。
public static void ReverseFast(string x)
{
StringBuilder reverse = new StringBuilder(x.Length);
for (int i = x.Length - 1; i >= 0; i--)
{
reverse.Append(x[i]);
}
Console.WriteLine(reverse);
}
以上解决方案比建议的重复问题答案更快。这个问题实际上是在5000 * 26个字符+范围内解决逆转问题。我仍然希望使用指针来测试这一点,以确定是否没有瓶颈,尤其是如此大量的字符。
答案 0 :(得分:13)
var arr = x.ToCharArray();
Array.Reverse(arr);
return new string(arr);
但请注意,这将反转任何unicode修饰符(重音符号等)。
基准:
Array.Reverse: 179ms
StringBuilder: 475ms
使用:
static void Main()
{
string text = new string('x', 100000);
GC.Collect();
GC.WaitForPendingFinalizers();
var watch = Stopwatch.StartNew();
const int LOOP = 1000;
for (int i = 0; i < LOOP; i++)
{
var arr = text.ToCharArray();
Array.Reverse(arr);
string y = new string(arr);
}
watch.Stop();
Console.WriteLine("Array.Reverse: {0}ms", watch.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
var reverse = new StringBuilder(text.Length);
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(text[j]);
}
string y = reverse.ToString();
}
watch.Stop();
Console.WriteLine("StringBuilder: {0}ms", watch.ElapsedMilliseconds);
}
如果我们尝试长度为500且循环500000次的字符串:
Array.Reverse: 480ms
StringBuilder: 1176ms
我也尝试在其中添加unsafe
,即
fixed (char* c = text)
{
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(c[j]);
}
}
这没有任何区别。
我也加入了JeffRSon的回答;我明白了:
Array.Reverse: 459ms
StringBuilder: 1092ms
Pointer: 513ms
(对于500长度×5000次迭代测试)
答案 1 :(得分:3)
这是一个基于指针的解决方案:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
int idx = s.Length;
fixed (char* c = s)
{
char* c1 = c;
while (idx != 0)
{
sarr[--idx] = *c1++;
}
}
return new String(sarr);
}
摆脱数组索引(sarr [ - idx])以下可能更快:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
fixed (char* c = s)
fixed (char* d = sarr)
{
char* c1 = c;
char* d1 = d + s.Length;
while (d1 > d)
{
*--d1 = *c1++;
}
}
return new String(sarr);
}
答案 2 :(得分:2)
在创建StringBuilder
时设置容量,这样就不必在循环期间增长并分配更多内存。将参数分配给局部变量是不必要的步骤,因为参数已经是局部变量。
public static void ReverseFast(string text) {
StringBuilder reverse = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--) {
reverse.Append(text[i]);
}
}
这只是删除任何不必要工作的基本步骤。如果您的代码确实存在性能问题,则需要分析生成的代码所执行的操作,并根据当前的框架和硬件创建不同的版本,以执行不同的操作。