【发布时间】:2013-03-10 01:27:11
【问题描述】:
我正在使用 Mergesort 订购 50.000.000 个字符串,根据我使用的参数类型有两种不同的结果。
使用 IComparable 接口:
- 20226 毫秒
直接使用字符串:
- 10912 毫秒
合并排序代码:
public class Mergesort2
{
static private StringComparer comparer1 = StringComparer.Ordinal;
public static void merge(IComparable[] a, IComparable[] aux, int lo, int mid, int hi)
{
for (int k = lo; k <= hi; k++)
{
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
a[k] = aux[j++];
}
else if (j > hi)
{
a[k] = aux[i++];
}
else if (less(aux[j], aux[i]))
{
a[k] = aux[j++];
}
else
{
a[k] = aux[i++];
}
}
}
private static void sort(IComparable[] a, IComparable[] aux, int lo, int hi)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid + 1, hi);
merge(a, aux, lo, mid, hi);
}
public static void sort(IComparable[] a)
{
IComparable[] aux = new IComparable[a.Length];
sort(a, aux, 0, a.Length - 1);
}
///*********************************************************************
/// Helper sorting functions
/// **********************************************************************
// is v < w ?
private static bool less(IComparable v, IComparable w)
{
return (comparer1.Compare(v, w) < 0);
}
// exchange a[i] and a[j]
private static void exch(Object[] a, int i, int j)
{
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/// <summary>
///*********************************************************************
/// Index mergesort
/// **********************************************************************
/// </summary>
// stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
private static void merge(IComparable[] a, int[] index, int[] aux, int lo, int mid, int hi)
{
// copy to aux[]
for (int k = lo; k <= hi; k++)
{
aux[k] = index[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
index[k] = aux[j++];
}
else if (j > hi)
{
index[k] = aux[i++];
}
else if (less(a[aux[j]], a[aux[i]]))
{
index[k] = aux[j++];
}
else
{
index[k] = aux[i++];
}
}
}
// return a permutation that gives the elements in a[] in ascending order
// do not change the original array a[]
public static int[] indexSort(IComparable[] a)
{
int N = a.Length;
int[] index = new int[N];
for (int i = 0; i < N; i++)
{
index[i] = i;
}
int[] aux = new int[N];
sort(a, index, aux, 0, N - 1);
return index;
}
// mergesort a[lo..hi] using auxiliary array aux[lo..hi]
private static void sort(IComparable[] a, int[] index, int[] aux, int lo, int hi)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, index, aux, lo, mid);
sort(a, index, aux, mid + 1, hi);
merge(a, index, aux, lo, mid, hi);
}
}
此代码会产生缓慢的运行时。
如果我将所有 IComparable 类型更改为 String,性能将会提高。为什么使用不同的类型会有如此巨大的性能差异?
【问题讨论】:
-
如果你把它变成通用的并使用
IComparable<T>来代替呢? -
是的,这是一个选项,但我对使用字符串并没有什么问题,我只是想了解其中的区别。
-
至少 100000000 次演员表是昂贵的。例如在
return (comparer1.Compare(v, w) < 0) -
StringComparer.Compare 对对象和字符串有不同的重载。字符串版本很可能是高度优化的,而对象版本只是为您提供“常规 .NET 性能”(鉴于其一般性质,编译器更难优化)。
-
object比较StringComparer有什么用?在我看来,它只是履行提供对象接口的合同义务。为什么你要使用StringComparer和字符串以外的任何东西对我来说似乎是个谜。我和@TimSchmelter 在这方面。毫无意义的演员表。
标签: c# .net string performance