I have created a simple console app and execute it from PerfView via Run Command -> PerfMonTest.exe
I get the log file and see the process of the app. It is expensive as expected (99% CPU ), but when I want to drill down into the expensive methods they are not shown in the list of expensive methods.
Is there something I can do to make them visible?
Here is the view when I selected the process. I would expect CallExpensive and CallCheap in the list:
Selecting the Main Methods doesnt give me the chace to drill further into the called methods
Here is the app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PerfMonTest
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i <= 2000; i++)
{
CallExpensive(1000);
CallCheap(1000);
CallCheap(400);
}
}
public static void CallExpensive(int expense)
{
for (int i = 0; i <= expense; i++)
{
DateTime checkTime = DateTime.Now;
string val = "10" + i.ToString();
}
}
public static void CallCheap(int expense)
{
for (int i = 0; i <= expense; i++)
{
int j = 2;
}
}
}
}
From the screenshots it looks like, you didn't load symbols. If you do, you'll see that most of the time is spent in DateTime.Now
.
If you click on Main
in the By Name view, you'll go to the Callers view, which will tell you which methods called Main
. If you want to drill into what methods Main
is calling, you need to go to the Callees view. If you do that, you'll see the break down of what Main
calls.
However, in this particular case the logic of CallExpensive
and CallCheap
is so simple, that the methods will be inlined (in release mode). Because the methods are inlined, they don't appear as part of the calls made from Main
as the code has been folded into Main
itself.
You can verify that the methods are inlined by attaching a debugger after the methods have run and look at the method descriptors for the type. Here's the output I got:
0:004> !dumpmt -md 004737c0
EEClass: 00471278
Module: 00472e94
Name: ConsoleApplication1.Program
mdToken: 02000002
File: C:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize: 0xc
ComponentSize: 0x0
Slots in VTable: 8
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
Entry MethodDe JIT Name
72064a00 71d66728 PreJIT System.Object.ToString()
72058830 71d66730 PreJIT System.Object.Equals(System.Object)
72058400 71d66750 PreJIT System.Object.GetHashCode()
72051790 71d66764 PreJIT System.Object.Finalize()
0047c01d 004737b8 NONE ConsoleApplication1.Program..ctor()
004d0050 00473794 JIT ConsoleApplication1.Program.Main(System.String[])
0047c015 004737a0 NONE ConsoleApplication1.Program.CallExpensive(Int32)
0047c019 004737ac NONE ConsoleApplication1.Program.CallCheap(Int32)
The fact that CallExpensive
and CallCheap
have NONE
listed in the JIT column indicates that they were inlined (or not called at all, but that's not the case here).