分析内部 .NET Framework 方法所花费的时间

Profile Time Spent in the Inner .NET Framework Methods

在 Visual Studio 中 - 有没有办法分析在 .NET Framework 的内部方法中花费的时间?

举个例子 - 考虑一个老式的 ArrayList,并向其添加一些随机数:

static void Main(string[] args)
{
    const int noNumbers = 10000;  // 10k
    ArrayList numbers = new ArrayList();
    Random random = new Random(1);  // use the same seed as to make
                                    //  benchmarking consistent
    for (int i = 0; i < noNumbers; i++)
    {
        int currentNumber = random.Next(10);  // generate a non-negative
                                              //  random number less than 10
        numbers.Add(currentNumber); // BOXING occurs here
    }
}

我可以在调试时很好地进入 .NET Framework 源代码。可以使用默认的 Microsoft 符号和 .NET 的源代码(如大约 5 年前 ) or go the dotPeek route (detailed ). As for the cleanest option of just using the Reference Source symbols - as Hans Passant was saying in his answer 中所述 - 创建符号的框架版本(直至安装的安全更新)必须完全匹配你的版本;你必须非常幸运才能让它工作(我没有)。底线 - 我可以成功地使用 2 种方法进入 .NET 源代码。

对于手头的示例,参考源代码和 dotPeek 逆向工程代码之间没有太大区别 - 即 ArrayListAdd 调用的方法 -即Capacitysetter和ArrayListEnsureCapacity,后者见下图(左边是ReferenceSource代码,右边是dotPeek源代码):

运行 "Instrumentation" 分析会话将 return 对每种方法所花费的时间进行细分,但只要 .NET 类型出现,似乎只有查看名为 "directly" 的相应代码的方法 - 在本例中为 Add 元素到 ArrayList 的函数,生成 Random int 的函数,以及相应的类型的构造函数。但是没有 EnsureCapacityCapacity 的 setter 的痕迹,它们都被 ArrayListAdd.

大量调用

向下钻取特定的 .NET 方法不会显示它依次调用的任何方法,也不会显示任何源代码(尽管能够更早地看到该代码,同时使用调试器进入):

如何才能看到那些额外的 "inner" .NET 方法?如果 Visual Studio 做不到,也许其他工具可以?

PS 有一个非常相似的问题 here,但是它已经有将近 10 年的历史了,而且没有多少可以说明这个问题。

稍后更新:正如 KolA 很好地指出的那样,JetBrains dotTrace 可以显示这一点。下面是逐行分析会话:

perhaps another tool can ?

如果您需要的话,DotTrace 可以将性能分析到属性。此示例适用于通用 List<T> 而不是 ArrayList,但我认为这无关紧要。