Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在这个简单的测试中,方法的速度与触发顺序有关?_C#_Performance - Fatal编程技术网

C# 为什么在这个简单的测试中,方法的速度与触发顺序有关?

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

我在做其他实验,直到这个奇怪的行为引起我的注意

代码在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 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();
}
}

您的问题是您的测试。在对代码进行基准测试时,应始终遵循以下几条指导原则:

  • 处理器关联:仅使用单个处理器,通常不使用#1
  • 预热:始终提前进行少量测试
  • 持续时间:确保您的测试持续时间至少为500毫秒
  • 平均值:将多个运行进行平均,以消除异常
  • 清理:强制GC在测试之间收集分配的对象
  • 冷却:让进程短时间睡眠
  • 因此,使用这些指导原则并重新编写测试,我得到以下结果:

    运行1

    Enter test number (1|2): 1 ListSum averages 776 ListSum averages 753 ArraySum averages 1102 ListSum averages 753 Press any key to continue . . . 输入测试编号(1 | 2):1 列表总数平均为776 列表总数平均为753 ArraySum平均值为1102 ListSum大街
    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;
        }
    }