-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
229 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,130 @@ | ||
# Ultra User Guide | ||
|
||
This is a default project description. | ||
## Quick Start | ||
|
||
> ____ | ||
> 🚨 The profiler **requires to run from an elevated prompt with administrative rights** 🚨 | ||
> | ||
> _This is required to allow to collect full stack traces, including kernel and native functions._ | ||
> ____ | ||
Example: open a **terminal with administrative rights**, to profile an executable called `my_commands.exe`: | ||
|
||
```console | ||
$ ultra.exe profile -- my_command.exe arg0 arg1 arg2... | ||
``` | ||
|
||
This will create a `ultra_my_command_..._.json.gz` trace file in the current directory. | ||
|
||
## Ultra Profiler UI | ||
|
||
In order to visualize a trace produced by `ultra.exe` you need to go to https://profiler.firefox.com/ and open the generated `json.gz` trace file. | ||
|
||
### Timeline | ||
|
||
This screenshot shows a profile captured with ultra and is available online [here](https://share.firefox.dev/3Cya7YW) | ||
|
||
You have access to several capabilities: | ||
- Zoom in a timeline | ||
- When in the Flame Graph / Stack Chart, you can hold `SHIFT + MouseWheel` to zoom-in / zoom-out | ||
|
||
![Timeline](profile_example.png) | ||
|
||
### Flame Graph / Stack Chart | ||
|
||
The Flame Graph / Stack Chart is a visualization of the time spent in functions. The width of the boxes is proportional to the time spent in the function. The boxes are stacked to show the call hierarchy. | ||
|
||
![Flame Graph](profile_flame_graph.png) | ||
|
||
### Categories | ||
|
||
When selecting functions, you can visualize the split between the time in the different modules: | ||
|
||
- `.NET`: Managed code (user or BCL) | ||
- `.NET JIT`: Functions participating in the JIT to compile methods | ||
- `.NET GC`: Functions participating in the GC | ||
- `.NET CLR`: Functions used by the CoreCLR runtime | ||
- `Native`: Native functions | ||
- `Kernel`: Kernel functions - displayed with hexadecimal address | ||
|
||
The colors are reflected in the Flame Graph / Stack Chart to easily spot the different usage. | ||
|
||
![Categories](profile_categories.png) | ||
|
||
While hovering the mouse over a function, you can see the time spent in the function and the categories: | ||
|
||
Here is an example of a function in the `JIT` category: | ||
|
||
![Category JIT)](profile_category_jit.png) | ||
|
||
|
||
Here is an example of a function in the `GC` category: | ||
|
||
![Category GC](profile_category_gc.png) | ||
|
||
### Memory Track | ||
|
||
The memory track shows the managed memory usage of the process. You can see the memory usage over time. | ||
|
||
![Profile Memory](profile_memory.png) | ||
|
||
## GC Allocation Track | ||
|
||
The GC Allocation Track shows the allocation rate of the process. You can see the allocation rate over time. | ||
|
||
![Profile GC Allocation](profile_gc_alloc.png) | ||
|
||
### JIT and GC Markers | ||
|
||
The JIT and GC markers are displayed in the timeline. You can see the JIT and GC events in the timeline. | ||
|
||
You can also see them in the Marker Chart and Marker Table view. | ||
|
||
![Profile JIT and GC Markers](profile_markers.png) | ||
|
||
## Ultra Command Line | ||
|
||
ultra.exe command line options: | ||
|
||
```console | ||
Usage: ultra [Options] command | ||
|
||
-h, -?, --help Show this message and exit | ||
-v, --version Show the version of this command | ||
--verbose Display verbose progress | ||
|
||
Available commands: | ||
profile Profile a new process or attach to an existing process | ||
convert Convert an existing ETL file to a Firefox Profiler json file | ||
``` | ||
|
||
## Profile | ||
|
||
This is the main command to profile an application - Only working within an elevated prompt: | ||
|
||
```console | ||
Usage: ultra profile [Options] <pid | -- execName arg0 arg1...> | ||
|
||
-h, -?, --help Show this message and exit | ||
--pid=PID The PID of the process to attach the profiler to. | ||
--sampling-interval=VALUE The VALUE of the sample interval in ms. Default is 8190Hz = 0.122ms. | ||
--symbol-path=VALUE The VALUE of symbol path. The default value is `;SRV*C:\Users\xoofx\AppData\Local\Temp\SymbolCache*https://msdl.microsoft.com/download/symbols;SRV*C:\Users\xoofx\AppData\Local\Temp\SymbolCache*https:// | ||
symbols.nuget.org/download/symbols`. | ||
--keep-merged-etl-file Keep the merged ETL file. | ||
--keep-intermediate-etl-files Keep the intermediate ETL files before merging. | ||
``` | ||
|
||
## Convert | ||
|
||
Convert an existing ETL file to a Firefox Profiler json file: | ||
|
||
It requires a list of PID in order to only produce results for these processes. | ||
|
||
```console | ||
Usage: ultra convert --pid xxx <etl_file_name.etl> | ||
|
||
-h, -?, --help Show this message and exit | ||
--pid=PID The PID of the process | ||
--symbol-path=VALUE The VALUE of symbol path. The default value is `;SRV*C:\Users\xoofx\AppData\Local\Temp\SymbolCache*https://msdl.microsoft.com/download/symbols;SRV*C:\Users\xoofx\AppData\Local\Temp\SymbolCache*https:// | ||
symbols.nuget.org/download/symbols`. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Ultra.Core | ||
|
||
Ultra is a an advanced profiler for .NET Applications available on Windows. | ||
|
||
Ultra.Core is the core library that contains the core functionalities of the Ultra profiler: | ||
|
||
- ETW sampling profiler via the class `EtwUltraProfiler` | ||
- Converter to Firefox Profiler format via the class `EtwConverterToFirefox` | ||
|
||
## 📖 User Guide | ||
|
||
For more details on how to use Ultra, please visit the [user guide](https://github.com/xoofx/Ultra/blob/main/doc/readme.md). | ||
|
||
## 🪪 License | ||
|
||
This software is released under the [BSD-2-Clause license](https://opensource.org/licenses/BSD-2-Clause). | ||
|
||
## 🤗 Author | ||
|
||
Alexandre Mutel aka [xoofx](https://xoofx.github.io). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,48 @@ | ||
namespace Ultra.Example; | ||
// Sample program using Markdig and Scriban to create a workload example for profiling with ultra | ||
|
||
/// <summary> | ||
/// Sample program using Markdig and Scriban to create a workload example for profiling with ultra | ||
/// </summary> | ||
internal class Program | ||
const int countBenchMarkdig = 500; | ||
const int countBenchScriban = 5000; | ||
var md = await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "CommonMark.md")); | ||
|
||
var benchMarkdig = () => | ||
{ | ||
static async Task Main(string[] args) | ||
for (int i = 0; i < countBenchMarkdig; i++) | ||
{ | ||
const int CountBenchMarkdig = 500; | ||
const int CountBenchScriban = 5000; | ||
|
||
var md = await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "CommonMark.md")); | ||
|
||
var benchMarkdig = () => | ||
{ | ||
for (int i = 0; i < CountBenchMarkdig; i++) | ||
{ | ||
var html = Markdig.Markdown.ToHtml(md); | ||
} | ||
}; | ||
|
||
var benchScriban = () => | ||
{ | ||
var template = Scriban.Template.Parse(""" | ||
{{ for $i in values }} | ||
[{{i}}] This is an example of a template with a loop | ||
{{ end }} | ||
"""); | ||
var html = Markdig.Markdown.ToHtml(md); | ||
} | ||
}; | ||
|
||
var values = new List<string> { "one", "two", "three" }; | ||
for (int i = 0; i < CountBenchScriban; i++) | ||
{ | ||
var text = template.Render(new { values = values }); | ||
} | ||
}; | ||
var benchScriban = () => | ||
{ | ||
var template = Scriban.Template.Parse(""" | ||
{{ for $i in values }} | ||
[{{i}}] This is an example of a template with a loop | ||
{{ end }} | ||
"""); | ||
|
||
var values = new List<string> { "one", "two", "three" }; | ||
for (int i = 0; i < countBenchScriban; i++) | ||
{ | ||
var text = template.Render(new { values = values }); | ||
} | ||
}; | ||
|
||
benchMarkdig(); | ||
benchMarkdig(); | ||
|
||
var tasks = new List<Task>(); | ||
var tasks = new List<Task>(); | ||
|
||
for (int i = 0; i < Math.Max(2, Environment.ProcessorCount / 4); i++) | ||
{ | ||
var markdigTask = new Task(benchMarkdig); | ||
var scribanTask = new Task(benchScriban); | ||
for (int i = 0; i < Math.Max(2, Environment.ProcessorCount / 4); i++) | ||
{ | ||
var markdigTask = new Task(benchMarkdig); | ||
var scribanTask = new Task(benchScriban); | ||
|
||
markdigTask.Start(); | ||
scribanTask.Start(); | ||
markdigTask.Start(); | ||
scribanTask.Start(); | ||
|
||
tasks.Add(markdigTask); | ||
tasks.Add(scribanTask); | ||
} | ||
tasks.Add(markdigTask); | ||
tasks.Add(scribanTask); | ||
} | ||
|
||
benchScriban(); | ||
benchScriban(); | ||
|
||
await Task.WhenAll(tasks); | ||
} | ||
} | ||
await Task.WhenAll(tasks); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"profiles": { | ||
"Ultra": { | ||
"commandName": "Project", | ||
"commandLineArgs": "convert --pid 472972 .\\ultra_Ultra.Example_2024-11-18_12_04_12.etl", | ||
"workingDirectory": "C:\\code\\Captures" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Markdig/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |