C# 为什么在这个简单的测试中,方法的速度与触发顺序有关?
我在做其他实验,直到这个奇怪的行为引起我的注意 代码在x64版本中编译 如果输入1,第三次运行列表方法的时间比前两次多40%。输出为C# 为什么在这个简单的测试中,方法的速度与触发顺序有关?,c#,performance,C#,Performance,我在做其他实验,直到这个奇怪的行为引起我的注意 代码在x64版本中编译 如果输入1,第三次运行列表方法的时间比前两次多40%。输出为 List costs 9312 List costs 9289 Array costs 12730 List costs 11950 Array costs 8082 Array costs 8086 List costs 11937 Array costs 12698 如果输入2,第三次运行数组方法比前2次运行花费的时间多30%。输出为 List costs
List costs 9312
List costs 9289
Array costs 12730
List costs 11950
Array costs 8082
Array costs 8086
List costs 11937
Array costs 12698
如果输入2,第三次运行数组方法比前2次运行花费的时间多30%。输出为
List costs 9312
List costs 9289
Array costs 12730
List costs 11950
Array costs 8082
Array costs 8086
List costs 11937
Array costs 12698
您可以看到该模式,完整的代码附在下面(只需编译并运行):
{提供的代码对于运行测试来说是最小的。用于获得可靠结果的实际代码更复杂,我包装了该方法,并在适当的预热后对其进行了100多次测试}
class ListArrayLoop
{
readonly int[] myArray;
readonly List<int> myList;
readonly int totalSessions;
public ListArrayLoop(int loopRange, int totalSessions)
{
myArray = new int[loopRange];
for (int i = 0; i < myArray.Length; i++)
{
myArray[i] = i;
}
myList = myArray.ToList();
this.totalSessions = totalSessions;
}
public void ArraySum()
{
var pool = myArray;
long sum = 0;
for (int j = 0; j < totalSessions; j++)
{
sum += pool.Sum();
}
}
public void ListSum()
{
var pool = myList;
long sum = 0;
for (int j = 0; j < totalSessions; j++)
{
sum += pool.Sum();
}
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
ListArrayLoop test = new ListArrayLoop(10000, 100000);
string input = Console.ReadLine();
if (input == "1")
{
sw.Start();
test.ListSum();
sw.Stop();
Console.WriteLine("List costs {0}",sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ListSum();
sw.Stop();
Console.WriteLine("List costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ArraySum();
sw.Stop();
Console.WriteLine("Array costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ListSum();
sw.Stop();
Console.WriteLine("List costs {0}", sw.ElapsedMilliseconds);
}
else
{
sw.Start();
test.ArraySum();
sw.Stop();
Console.WriteLine("Array costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ArraySum();
sw.Stop();
Console.WriteLine("Array costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ListSum();
sw.Stop();
Console.WriteLine("List costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
test.ArraySum();
sw.Stop();
Console.WriteLine("Array costs {0}", sw.ElapsedMilliseconds);
}
Console.ReadKey();
}
}
类ListArrayLop
{
只读int[]myArray;
只读列表;
只读全集会话;
公共ListArrayLoop(int loopRange,int totalSessions)
{
myArray=新整数[loopRange];
for(int i=0;i
人为的问题会给你人为的答案
优化应该在编写代码之后而不是之前完成。以最容易理解和维护的方式编写解决方案。然后,如果程序对于您的用例来说速度不够快,那么您可以使用a,然后返回,看看实际的瓶颈在哪里,而不是您“认为”它在哪里
在您的情况下,人们尝试进行的大多数优化都是花费6个小时来做一些可以将运行时间减少1秒的事情。大多数小程序的运行时间不足以抵消您尝试“优化”它所花费的成本
尽管如此,这是一个奇怪的边缘案例。我对它做了一点修改,并正在通过探查器运行它,但我需要降级我的VS2010安装,这样我就可以让.NET framework源代码退一步
我使用更大的示例运行了探查器,我找不到很好的理由说明它需要更长的时间。评论太多了,所以它是CW--请随意合并,我将删除它。给定的代码对我来说有点不合适,但问题仍然很有趣。如果混合调用,性能会变差。这段代码突出显示了它:
static void Main(string[] args)
{
var input = Console.ReadLine();
var test = new ListArrayLoop(10000, 1000);
switch (input)
{
case "1":
Test(test.ListSum);
break;
case "2":
Test(test.ArraySum);
break;
case "3":
// adds about 40 ms
test.ArraySum();
Test(test.ListSum);
break;
default:
// adds about 35 ms
test.ListSum();
Test(test.ArraySum);
break;
}
}
private static void Test(Action toTest)
{
for (int i = 0; i < 100; i++)
{
var sw = Stopwatch.StartNew();
toTest();
sw.Stop();
Console.WriteLine("costs {0}", sw.ElapsedMilliseconds);
sw.Reset();
}
}
static void Main(字符串[]args)
{
var input=Console.ReadLine();
var测试=新的ListArrayLop(10000,1000);
开关(输入)
{
案例“1”:
测试(Test.ListSum);
打破
案例“2”:
试验(阵列试验);
打破
案例“3”:
//增加大约40毫秒
test.ArraySum();
测试(Test.ListSum);
打破
违约:
//增加大约35毫秒
test.ListSum();
试验(阵列试验);
打破
}
}
专用静态空隙试验(动作试验)
{
对于(int i=0;i<100;i++)
{
var sw=Stopwatch.StartNew();
toTest();
sw.Stop();
WriteLine(“costs{0}”,sw.elapsedmillesons);
sw.Reset();
}
}
您的问题是您的测试。在对代码进行基准测试时,应始终遵循以下几条指导原则:
public static int Sum(this IEnumerable<int> source)
{
int num = 0;
foreach (int num2 in source)
num += num2;
return num;
}
public static int Sum(this IEnumerable<int> source)
{
int num = 0;
IEnumerator<int> Enumerator = source.GetEnumerator();
while(Enumerator.MoveNext())
num += Enumerator.Current;
return num;
}
public static class FasterSumExtensions
{
public static int Sum(this int[] source)
{
int num = 0;
foreach (int num2 in source)
num += num2;
return num;
}
public static int Sum(this List<int> source)
{
int num = 0;
foreach(int num2 in source)
num += num2;
return num;
}
}
public static class EvenFasterSumExtensions
{
public static int Sum(this int[] source)
{
int num = 0;
for(int i = 0; i < source.Length; i++)
num += source[i];
return num;
}
public static int Sum(this List<int> source)
{
int num = 0;
for(int i = 0; i < source.Count; i++)
num += source[i];
return num;
}
}