通用扩展方法比非通用扩展方法慢
Generic extension method is slower than non-generic extension method
我为列表编写了一个扩展方法,用于在排序列表中查找给定值(或下一个更大的值)的索引。
public static int LinearSearch(this List<int> list, int startIndex, int value)
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
public static int LinearSearch<T>(this List<T> list, int startIndex, T value) where T : IComparable
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
如您所见,我曾经写过一次通用的,一次专门针对整数。如果我注释掉特定于 int 的版本,我的代码运行速度大约要慢得多,就好像我证明了两者一样(假设我在 int-lists 上工作)。
如何使通用版本与非通用版本一样快?我不想复制和粘贴我的代码来获得整数和长整数的性能。
该测试对 1,000 个整数的排序列表运行 10,000,000 次随机查询。
LinearSearch took 9823 ms // generic
LinearSearch took 1553 ms // int-specific
性能测量的测试代码
class Program
{
const int count = 1000;
const int runs = 10_000_000;
static List<int> list = new List<int>();
static List<int> queries = new List<int>();
static void Main(string[] args)
{
MeasureRuntime(CreateTestData);
MeasureRuntime(LinearSearch);
}
private static void LinearSearch()
{
foreach (int query in queries)
list.LinearSearch(query);
}
private static void CreateTestData()
{
Random random = new Random(0);
list.Add(0);
for (int i = 0; i < count; i++) list.Add(list[list.Count - 1] + random.Next(0, 10));
for (int i = 0; i < runs; i++) queries.Add(random.Next(0, list.Count - 1));
}
private static void MeasureRuntime(Action action)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
action();
stopwatch.Stop();
Console.WriteLine($"{action.GetMethodInfo().Name} took {stopwatch.ElapsedMilliseconds} ms");
}
}
问题是我使用了非通用版本 IComparable
而不是 IComparable<T>
,这导致了性能下降。现在,使用 IComparable<T>
通用版本的运行速度与特定类型版本一样快。
public static int LinearSearch<T>(this List<T> list, int startIndex, T value)
where T : IComparable<T>
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
我为列表编写了一个扩展方法,用于在排序列表中查找给定值(或下一个更大的值)的索引。
public static int LinearSearch(this List<int> list, int startIndex, int value)
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
public static int LinearSearch<T>(this List<T> list, int startIndex, T value) where T : IComparable
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}
如您所见,我曾经写过一次通用的,一次专门针对整数。如果我注释掉特定于 int 的版本,我的代码运行速度大约要慢得多,就好像我证明了两者一样(假设我在 int-lists 上工作)。
如何使通用版本与非通用版本一样快?我不想复制和粘贴我的代码来获得整数和长整数的性能。
该测试对 1,000 个整数的排序列表运行 10,000,000 次随机查询。
LinearSearch took 9823 ms // generic
LinearSearch took 1553 ms // int-specific
性能测量的测试代码
class Program
{
const int count = 1000;
const int runs = 10_000_000;
static List<int> list = new List<int>();
static List<int> queries = new List<int>();
static void Main(string[] args)
{
MeasureRuntime(CreateTestData);
MeasureRuntime(LinearSearch);
}
private static void LinearSearch()
{
foreach (int query in queries)
list.LinearSearch(query);
}
private static void CreateTestData()
{
Random random = new Random(0);
list.Add(0);
for (int i = 0; i < count; i++) list.Add(list[list.Count - 1] + random.Next(0, 10));
for (int i = 0; i < runs; i++) queries.Add(random.Next(0, list.Count - 1));
}
private static void MeasureRuntime(Action action)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
action();
stopwatch.Stop();
Console.WriteLine($"{action.GetMethodInfo().Name} took {stopwatch.ElapsedMilliseconds} ms");
}
}
问题是我使用了非通用版本 IComparable
而不是 IComparable<T>
,这导致了性能下降。现在,使用 IComparable<T>
通用版本的运行速度与特定类型版本一样快。
public static int LinearSearch<T>(this List<T> list, int startIndex, T value)
where T : IComparable<T>
{
for (int i = startIndex; i < list.Count; i++)
if (list[i].CompareTo(value) >= 0)
return i;
return -1;
}