Professional Documents
Culture Documents
Josh Williams
Microsoft Corporation
Blog: http://blogs.msdn.com/joshwil/
Legal Information
The information contained in this document represents the current view of Micros
oft Corporation on the issues discussed as of the date of publication. Because
Microsoft must respond to changing market conditions, it should not be interpret
ed to be a commitment on the part of Microsoft, and Microsoft cannot guarantee t
he accuracy of any information presented after the date of publication.
This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANT
IES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.
Complying with all applicable copyright laws is the responsibility of the user.
Without limiting the rights under copyright, no part of this document may be re
produced, stored in or introduced into a retrieval system, or transmitted in any
form or by any means (electronic, mechanical, photocopying, recording, or other
wise), or for any purpose, without the express written permission of Microsoft C
orporation.
Mission Statement
PerfConsole was designed to be
- Lightweight (requiring nothing more than a base .Net 2.0 install) ana
lysis
- Simple to learn and use
- Easily extendable
- Useful for investigation
- Useful for automation
About PerfConsole
PerfConsole can be driven in two modes:
1) In console mode (pass /console on the command line) all output will be lim
ited to the console window. In this mode it is recommended that you set your con
sole to some large width in order for things to show up correctly.
2) In console/winforms mode (the default) you can drive things from the con
sole window, but whenever interesting data is generated it is displayed in a new
window which then has GUI navigation to continue drilling into that data set.
I expect that most people will use PerfConsole in the default mode; however for
the hardcore the console can be surprisingly efficient -- it is kind of the equi
valent to debugging using Visual Studio vs. debugging using WinDbg .
We will then get into more interesting pieces like the Windows Forms-based outpu
t and investigation mode. Since this mode is fundamentally based on the same com
mand syntax and data model as the console mode, it is highly recommended that yo
u read straight through.
Syntax
To understand PerfConsole it helps to have a basic grasp of the command line syn
tax:
@name
Access a temporary data object named <name>; this includes loaded profiles or sa
ved results of command execution
{x, y}
Create a tuple with elements x and y. These elements can be profiles, temporarie
s or command sequences
|
Command separator
;
Command sequence separator
At the core of PerfConsole are Profile objects, which can contain some set of da
ta including FunctionSummaryData, ModuleSummaryData, CallerCalleeData, CallTreeD
ata and ProfileInfo. Depending on the type of profile imported some of these may
not be useful. Generally however given the default usage of the tool they will
all be available.
To make use of the data there is the concept of commands that know how to manipu
late the shape of data (e.g. find a specific function, sort the modules, get n i
tems from a list). These commands can be applied to a profile s data set in order
to gain useful information about the performance characteristics of the profile
application.
As input a command accepts some data object and optionally some set of other inp
uts (e.g. strings, integers, enum values, etc). The command s output is typically
some other data object which can be consumed by other commands, making commands
composeable:
For instance, the command above takes all functions out of profile @name, sorts
them by exclusive time and then returns the top 30. This is the PerfConsole logi
cal equivalent to the statement the top 30 exclusive functions in profile @name .
we can break it down by saying that there is some PerfData object which is input
to the functions command (in this case Profile @name), and the functions comman
d returns some PerfData object (in this case a FunctionSummaryData) which is pas
sed as input[1] to the sort command, and the output of the sort command is passe
d as input to the top command. This is much like the Windows or Unix command she
ll, except instead of text what is being passed along from command to command is
a strongly typed object. Generally commands will narrow the type of object that
they accept by specifying that it must implement some interface or be some exac
t type. This allows the system to provide better error messages when commands ar
e combined with incompatible data types, and it also assists in automatically bu
ilding good help output.
Looking at the help[2] for the functions command we can see that it returns a Fu
nctionSummaryData object, however the help for the sort command indicates that
it only accepts an object of type ISortable. Note that the help output follows t
he standard | conventions: input to the left of the command, output to the right
.
> ? functions
Get the function data out of a profile.
Usage:
Profile | functions | FunctionSummaryData
> ? sort
Sort a IPerfDataSortableList (e.g. FunctionSummary, ModuleSummary). Each type
has its own sort types (e.g. 'name', 'address', 'exclusive', etc...).
Usage:
ISortable | sort <field:SortField> | ISortable
ISortable | sort <field:SortField> <direction:SortDirection> | ISortable
There are a special set of interfaces (all declared as nested types of PerfData)
which objects are allowed to implement and are allowed to be the input and outp
ut types of commands. Using the help built into PerfConsole and the special comm
and print type it becomes easy to discover what data type is returned by a comma
nd and what interfaces it implements, For example:
Properties:
Count
Name
Here you can see that the data type is preserved through the commands even thoug
h sort returns an ISortable and top returns an IList, as underneath the Function
SummaryData which is being manipulated implements both of those interfaces.
There is an additional form of the help command which takes in a PerfData object
(much like the print type command), but instead returns a list of other strongly
typed commands which will accept the output data object as an input. This can be
a very useful way to experiment with the system and figure out how commands com
pose together.
Commands
PerfConsole contains a set of built in commands which are very useful for shapin
g data into useful forms to gather information during a performance investigatio
n:[3]
Base Commands
Help / ?
Display help. This can come in a number of forms:
1) Listing the commands which are currently loaded: help
2) Showing help for a specific command: help <command name>
3) Showing a list of commands that will work with a specific input data obj
ect: <command that produces object> | help
??
Display this document.
Load
Load a profile or extension command DLL from disk. The default is to load a Prof
ile, using load <profile filename> .
Save
Save an object into a temporary. As seen in the syntax section of this document,
temporaries are denoted by @name.
Set
View and change PerfConsole application settings.
Cls
Clear the console screen.
Null
Return the special PerfData derived null object; currently its only use is to cl
ear a specific temporary (using null | save tempname ).
Addpath
Add lookup paths for command dlls, profiles or source. Source paths are also pic
ked up from the configuration file and through the _NT_SOURCE_PATH environment v
ariable.
Exit / Q / Quit
Leave the PerfConsole
Profile Commands
Functions
Get the FunctionSummaryData object out of a profile.
Modules
Get the ModuleSummaryData object out of a profile.
Butterfly
Get the CallerCalleeData object out of a profile.
Calltree
Get the CallTreeData object out of a profile.
ProfileInfo
Get the ProfileInfo object out of a profile
Output Commands
Print
Prints the result of a command to the console. In /console mode this is the defa
ult command executed at the end of a command sequence that returns a non-null Pe
rfData object. Print can also be used with the type or html arguments which control
the output:
- type shows the type of data object which is passed in, including implem
ented interfaces and public properties
- html takes the resulting PerfData object from a command sequence and co
nverts it to html.
If given an output filename the print command will save the results to a file on
disk.
Form
Opens a form with the results of the command displayed as html. When not in /con
sole mode this is the default command executed at the end of a command sequence
that returns a non-null PerfData object.[6]
State Commands
Show
Shows interesting state of PerfConsole (e.g.: settings, loaded profiles, current
temporaries)
Label
Output a label to the console, which can be useful for reporting purposes.
Cleartemps
Clear all temporaries currently stored.
Commands in PerfConsole are composable, and you aren t limited to using a single c
ommand only once in a command sequence. For instance, the following is perfectly
legal:
which says give me the top 10 exclusive time functions sorted by name . Or:
> functions @name | trim Inclusive > 10 | trim Inclusive < 40 | sort Inclusive
which says give me the list of functions with inclusive times between 10 and 40%,
sorted by inclusive time . It is notable that you can use shorthand versions of e
num values as long as you include enough information to fully disambiguate which
value you mean, so:
Results in a useful overview of where time is spend. Here is what this looks lik
e in console mode:
Forms
If you run PerfConsole in its default mode you will get the console/winforms mod
e. This mode acts like a console pretty much until it decides to act like a Wind
ows Forms app, which is any time there is interesting data to visualize.
When you start with something as simple as the command functions @name in form mod
e you will be presented with the following:
Here we can see that the FunctionSummaryData object rendered itself as HTML and
was pushed into a form which knows how to display HTML. Notice the context menu
when I right-clicked over one of the links. This shows you the actions which are
hard coded into the UI of things you can do with that data element. In this cas
e you can:
If you just click the link then the first command in the context menu is execute
d, in this case showing you the butterfly view centered on that function. Additi
onally, you can enter new commands or variations on current commands in the comm
and execution text box at the top of the window. If you pull down the combo box
you will see a history of the commands that you executed to get to this point an
d you can choose to go back and see the results again (the back/forward buttons
also work for this purpose).
Here are some other interesting views
1) A call tree showing all the functions called by __main__.Proc0$f5(object)
2) A call tree showing all the unique call trees of depth 9 which called CallCom
pileMethodWithSEHWrapper:
Generally it is recommended that you play with the interface to get a feel for i
t. And rest assured that it will get prettier over time.
It helps to get used to the syntax by first staring to play with PerfConsole in
/console mode -- there you can explore the composability of commands.
It is notable that the PerfConsole forms output is just HTML and can be cut/past
ed directly into outlook and emailed. Additionally you can save the HTML or prin
t directly from the application.
Scripting
One of the interesting uses of PerfConsole will be in automation programs. For t
hose purposes it is notable that PerfConsole can execute commands which are pass
ed as command line arguments. E.g.:
Here PerfConsole will start up in console mode, load the profile data\prof3.vsp,
print out the top 10 exclusive functions to the console and quit. Put together
with macros and extension dlls this can become a very powerful mechanism for aut
omated performance reporting. Use /? from the command line to see this and other
argument options.
Extension Dlls
Extensibility in PerfConsole comes from extension command dlls. These are simple
managed dlls which have some number of types marked with a special attribute ([
PerfConsoleCustomCommand]) indicating that they are commands which derive from P
erfConsole.Commands.Command. Here is the definition for Command:
By deriving from this type you can create any extended functionality that you wa
nt for PerfConsole. However, you have to do all that pesky string parsing yourse
lf, taking care to follow all the same rules as the rest of the commands for par
sing and validating parameters (there is a helper for splitting input strings, C
ommand.SplitParameters() which promotes consistency between commands. Additional
ly if other commands want to reuse the code that your command implements they ar
e going to have to pass long hard-to-debug strings to your command to control it
s behavior. Given this I have provided a derivative of Command named ReflectionC
ommand which eliminates all of these hassles. It handles the parsing of the comm
and line and strong typing of command invocation method parameters, therefore al
lowing easy reuse in a way that any C# programmer is used to. This allows you to
implement a new command to (for instance) find all jit helpers by easily reusing
a number of the built in commands:
Here we are able to pass an enum to the sort command and a string to the find co
mmand while passing no extraneous data to the functions command. ReflectionComma
nd allows easy creation of strongly typed command invocation methods (additional
ly automatically creating usage output based on the typing of input and output a
rguments). If you derive from ReflectionCommand instead of Command you get this
for free simply by creating static command invocation methods that conform to th
e following set of rules.
The ReflectionCommand type then takes the responsibility to implement the Usage
getter as well as InvokeCommand method and dispatch to your declared invocation
methods at runtime when the command is invoked from the console. This also allow
s for easy reuse of your commands by other commands and eliminates the hassle of
string parsing in every command instead allowing you to have strongly typed inp
ut parameter types like enums.[7] While they don t fall into rules per se, there a
re also a set of recommendations for implementing external commands derived from
ReflectionCommand:
Here is an example of a simple command that computes the sum of all the exclusiv
e or inclusive time of the elements in a list using the ReflectionCommand mechan
ism:
[PerfConsoleCustomCommand]
class Sum : ReflectionCommand
{
static readonly string name = "sum";
static readonly string help = "Print the sum of either the Inclusive or
Exclusive percentages of all the entries in a list.";
switch (fieldToSum)
{
case PerfData.Field.Exclusive:
for (int i=0; i<data.Count; i++)
{
IBaseEntry entry = (IBaseEntry)data.GetItem(i);
sum += entry.ExclusivePercentage;
}
sl.Add(String.Format("Exclusive Sum={0:p}.", sum/100));
break;
case PerfData.Field.Inclusive:
for (int i=0; i<data.Count; i++)
{
IBaseEntry entry = (IBaseEntry)data.GetItem(i);
sum += entry.InclusivePercentage;
}
sl.Add(String.Format("Incluisve Sum={0:p}.", sum/100));
break;
}
return sl;
}
}
Current Extension Dlls
Here is a list of the extensions that I have implemented so far. As mentioned be
fore these are loaded using the load CommandDll command.
Configuration File
PerfConsole has a simple configuration file pc.config that resides in the same d
irectory as the executable. It is not required, but it does allow for a number o
f customizations. These include
- Command dll lookup paths, profile lookup paths and source lookup path
s
- Extension command dlls to be loaded at startup
- Default public settings (what can be changed at runtime using the set c
ommand).
- Source file editor (the default is notepad). Note that %line and %fil
e are special and are replaced at runtime with the line number and file name.
populated with the .exe name of your editor only. Full path to .exe
is
preferred
-->
<Editor>notepad.exe</Editor>
<EditorArgs>/g %line %file</EditorArgs>
</External>
</PerfConsole>
[1] Commands implicitly clone the incoming data such that the original data is n
ot modified by the command. This means that you can t apply the sort command to th
e function list of a profile and assume that it is sorted that way from then on.
This feature prevents you from being destructive to your original data and enab
les multiple concurrent views of the same data without conflict. It is possible
to save the result of a command into a temporary variable using the save command
.
[2] It is useful to understand the output of the help command in order to discov
er what commands work together. See the section on commands for more information
.
[3] It is highly recommended that you use the help command to investigate the ex
act semantics of these commands.
[4] When applied to a CallTreeData object the trim command will terminate all br
anches at the first node which passes below the threshold.
[5] When applied to a CallTreeData object the find command will find all nodes w
hich match the search criteria and promote them to the root level, bringing alon
g their callers. Thus if you specify a query that can match multiple items e.g. f
ind Name Contains System.String you will end up with a branch from the root for e
ach method in System.String.
[6] Things which wouldn t make sense to display in a form are still displayed on t
he console, e.g. results from help, print, set, etc
[7] It additionally allows for some neat functionality in the help command where
it can at runtime lookup which commands will accept a specific PerfData derived
object as input and present the user with a list.