当我对一个程序进行采样并且它实际上比不进行分析时运行得更快时,为啥会这样?

Posted

技术标签:

【中文标题】当我对一个程序进行采样并且它实际上比不进行分析时运行得更快时,为啥会这样?【英文标题】:How Come when I sampling profile a program and it actually runs faster than not profiling?当我对一个程序进行采样并且它实际上比不进行分析时运行得更快时,为什么会这样? 【发布时间】:2011-09-22 15:05:03 【问题描述】:

我使用 DotTrace 4.5 性能

释放模式时间:

 2400000000
 Basic: 00:00:08.8051103
 2400000000
 Five: 00:00:09.1561338
 2400000000
 Overload: 00:00:16.3740938
 2400000000
 IListtoFive: 00:00:15.5841445

在发布模式下进行分析的时间。

 2400000000
 Basic: 00:00:01.0048224
 2400000000
 Five: 00:00:03.5416982
 2400000000
 Overload: 00:00:11.8009959
 2400000000
 IListtoFive: 00:00:11.2568770

我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace testLineIndex


    class Program
    
        static long Five(int s0, int s1, int s2, int s3, int s4)
        
            return s4 + 100 * s3 + 10000 * s2 + 1000000 * s1 + 100000000 * s0;
        

        static long Overload(IList<int> line)
        
            return Five(line[0], line[1], line[2], line[3], line[4]);
        

        static long IListtoFive(IList<int> line)
        
            return line[0]+100* line[1]+10000* line[2]+1000000* line[3]+100000000*line[4];
        

        static void Main(string[] args)
        
            Stopwatch watch = new Stopwatch();

            long testSize = 400000000;
            //List<int> myList = new List<int>  1, 2, 3, 4, 5 ;
            int[] myList = new int[]  1, 2, 3, 4, 5 ;
            long checksum = 0;
            watch.Start();
            for (long i = 0; i < testSize; i++)
            
                long ret = Five(1,2,3,4,5);
                checksum += ret % 9;
            
            watch.Stop();
            Console.WriteLine(checksum);
            Console.WriteLine("Basic: 0", watch.Elapsed);

            checksum = 0;
            watch.Restart();
            for (long i = 0; i < testSize; i++)
            
                long ret = Five(myList[0], myList[1], myList[2], myList[3], myList[4]);
                checksum += ret % 9;
            
            watch.Stop();
            Console.WriteLine(checksum);
            Console.WriteLine("Five: 0",watch.Elapsed);

            checksum = 0;
            watch.Restart();
            for (long i = 0; i < testSize; i++)
            
                long ret = Overload(myList);
                checksum += ret % 9;
            
            watch.Stop();
            Console.WriteLine(checksum);
            Console.WriteLine("Overload: 0", watch.Elapsed);

            checksum = 0;
            watch.Restart();
            for (long i = 0; i < testSize; i++)
            
                long ret = IListtoFive(myList);
                checksum += ret % 9;
            
            watch.Stop();
            Console.WriteLine(checksum);
            Console.WriteLine("IListtoFive: 0", watch.Elapsed);
            Console.ReadKey();
        
    

【问题讨论】:

只是澄清一下-您是在问“为什么程序在发布模式下比在调试模式下运行得更快?” 我想我现在明白了——你在问为什么分析似乎加速了应用程序(而不是仅仅运行它)。问题-您的基线编号是在 VS 中运行还是仅运行已编译的 EXE 时出现的? @ChrisShain 非常感谢,你说得对!我在 VS 中运行它,但编译后的 exe ......我通过在没有 VS 的情况下运行 exe 再次检查,它变得更快。虽然我不知道为什么速度会不同。你能给我一个详细的答案吗?我会将其标记为正确答案。 您是否在运行探查器后立即运行探查器?通常连续多次执行代码会在执行优化和缓存内容时加快速度。 @colinfang:当然,在调试器中运行与不在调试器中运行时的速度不同。当您在调试器下运行代码时,CLR 会花时间与调试器通信,垃圾收集器变得不那么激进,因此当您可能在调试器中查看资源时它不会清理资源,抖动会生成效率较低的代码这样更容易调试,等等。如果附加了调试器,您将无法获得任何可靠的性能数据。 【参考方案1】:

我怀疑是调试器。即使您在发布模式下运行它,从 VS 运行它也会附加调试器,这会大大减慢它的速度。

【讨论】:

+1。取消选中 Tools->Options->Debugging->"Suppress JIT Optimizatons..." 可以减少将调试器附加到发布版本的影响 我遇到了同样的问题(10 倍的性能损失),我发现主要的罪魁祸首是“启用非托管代码调试”,在 Visual Studio 中是not处于调试状态选项,(我想这太有意义了),而是在项目属性的调试选项卡中。 P.S.这个问题与几个月前发布的***.com/questions/5417663/… 重复。

以上是关于当我对一个程序进行采样并且它实际上比不进行分析时运行得更快时,为啥会这样?的主要内容,如果未能解决你的问题,请参考以下文章

Java频率分析性能

探查器如何对正在运行的程序进行采样?

用MATLAB设计对信号进行频谱分析和滤波处理的程序

是否可以使用 VS2010 分析器对 C# 中的主线程以外的线程进行采样

使用 /proc/*/stat 进行分析

使用 AWS Glue 爬虫进行智能采样