Skip to content

Commit aae4f43

Browse files
authored
Prototype collecting memory (#66)
* Prototype collecting memory * first stab at summary * Add global.json * 8.0.2xx sdk mininum * Fix GC, SelfGC, and memory counts * Use version deployed on macos image * Use latest feature * Add total memory to .NET Framework version * Refactor code and add views * Fix tests
1 parent 784e344 commit aae4f43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1902
-1446
lines changed

Profiler/Profiler.Format.ps1xml

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@
3434
<Label>Top50FunctionSelfDuration</Label>
3535
<ScriptBlock>'List top 50 functions based on time consumed directly by the function'</ScriptBlock>
3636
</ListItem>
37+
<ListItem>
38+
<Label>Top50Memory</Label>
39+
<ScriptBlock>'List top 50 lines based on the memory consumed'</ScriptBlock>
40+
</ListItem>
41+
<ListItem>
42+
<Label>Top50SelfMemory</Label>
43+
<ScriptBlock>'List top 50 lines based on the memory consumed directly by the line'</ScriptBlock>
44+
</ListItem>
3745
<ListItem>
3846
<Label>AllLines</Label>
3947
<ScriptBlock>'Show all lines processed by profiler trace'</ScriptBlock>
@@ -609,5 +617,198 @@
609617
</TableRowEntries>
610618
</TableControl>
611619
</View>
620+
621+
<!-- Memory views -->
622+
<View>
623+
<Name>Profiler.MemoryView</Name>
624+
<ViewSelectedBy>
625+
<TypeName>Profiler.MemoryView</TypeName>
626+
</ViewSelectedBy>
627+
<TableControl>
628+
<AutoSize />
629+
<TableHeaders>
630+
<TableColumnHeader>
631+
<Alignment>Right</Alignment>
632+
</TableColumnHeader>
633+
<TableColumnHeader>
634+
<Alignment>Right</Alignment>
635+
</TableColumnHeader>
636+
<TableColumnHeader>
637+
<Alignment>Right</Alignment>
638+
</TableColumnHeader>
639+
<TableColumnHeader>
640+
<Alignment>Right</Alignment>
641+
</TableColumnHeader>
642+
<TableColumnHeader>
643+
<Alignment>Right</Alignment>
644+
</TableColumnHeader>
645+
<TableColumnHeader>
646+
<Alignment>Right</Alignment>
647+
</TableColumnHeader>
648+
<TableColumnHeader>
649+
<Alignment>Left</Alignment>
650+
</TableColumnHeader>
651+
<TableColumnHeader>
652+
<Alignment>Right</Alignment>
653+
</TableColumnHeader>
654+
<TableColumnHeader>
655+
<Alignment>Left</Alignment>
656+
</TableColumnHeader>
657+
<TableColumnHeader>
658+
<Alignment>Right</Alignment>
659+
</TableColumnHeader>
660+
<TableColumnHeader>
661+
<Alignment>Left</Alignment>
662+
</TableColumnHeader>
663+
<TableColumnHeader>
664+
<Alignment>Left</Alignment>
665+
</TableColumnHeader>
666+
<TableColumnHeader>
667+
<Alignment>Left</Alignment>
668+
</TableColumnHeader>
669+
</TableHeaders>
670+
<TableRowEntries>
671+
<TableRowEntry>
672+
<TableColumnItems>
673+
<TableColumnItem>
674+
<PropertyName>MemoryPercent</PropertyName>
675+
</TableColumnItem>
676+
<TableColumnItem>
677+
<PropertyName>Memory</PropertyName>
678+
</TableColumnItem>
679+
<TableColumnItem>
680+
<PropertyName>Gc</PropertyName>
681+
</TableColumnItem>
682+
<TableColumnItem>
683+
<PropertyName>SelfMemoryPercent</PropertyName>
684+
</TableColumnItem>
685+
<TableColumnItem>
686+
<PropertyName>SelfMemory</PropertyName>
687+
</TableColumnItem>
688+
<TableColumnItem>
689+
<PropertyName>SelfGc</PropertyName>
690+
</TableColumnItem>
691+
<TableColumnItem>
692+
<PropertyName>Duration</PropertyName>
693+
</TableColumnItem>
694+
<TableColumnItem>
695+
<PropertyName>HitCount</PropertyName>
696+
</TableColumnItem>
697+
<TableColumnItem>
698+
<PropertyName>File</PropertyName>
699+
</TableColumnItem>
700+
<TableColumnItem>
701+
<PropertyName>Line</PropertyName>
702+
</TableColumnItem>
703+
<TableColumnItem>
704+
<PropertyName>Module</PropertyName>
705+
</TableColumnItem>
706+
<TableColumnItem>
707+
<PropertyName>Function</PropertyName>
708+
</TableColumnItem>
709+
<TableColumnItem>
710+
<PropertyName>Text</PropertyName>
711+
</TableColumnItem>
712+
</TableColumnItems>
713+
</TableRowEntry>
714+
</TableRowEntries>
715+
</TableControl>
716+
</View>
717+
718+
<View>
719+
<Name>Profiler.SelfMemoryView</Name>
720+
<ViewSelectedBy>
721+
<TypeName>Profiler.SelfMemoryView</TypeName>
722+
</ViewSelectedBy>
723+
<TableControl>
724+
<AutoSize />
725+
<TableHeaders>
726+
<TableColumnHeader>
727+
<Alignment>Right</Alignment>
728+
</TableColumnHeader>
729+
<TableColumnHeader>
730+
<Alignment>Right</Alignment>
731+
</TableColumnHeader>
732+
<TableColumnHeader>
733+
<Alignment>Right</Alignment>
734+
</TableColumnHeader>
735+
<TableColumnHeader>
736+
<Alignment>Right</Alignment>
737+
</TableColumnHeader>
738+
<TableColumnHeader>
739+
<Alignment>Right</Alignment>
740+
</TableColumnHeader>
741+
<TableColumnHeader>
742+
<Alignment>Right</Alignment>
743+
</TableColumnHeader>
744+
<TableColumnHeader>
745+
<Alignment>Left</Alignment>
746+
</TableColumnHeader>
747+
<TableColumnHeader>
748+
<Alignment>Right</Alignment>
749+
</TableColumnHeader>
750+
<TableColumnHeader>
751+
<Alignment>Left</Alignment>
752+
</TableColumnHeader>
753+
<TableColumnHeader>
754+
<Alignment>Right</Alignment>
755+
</TableColumnHeader>
756+
<TableColumnHeader>
757+
<Alignment>Left</Alignment>
758+
</TableColumnHeader>
759+
<TableColumnHeader>
760+
<Alignment>Left</Alignment>
761+
</TableColumnHeader>
762+
<TableColumnHeader>
763+
<Alignment>Left</Alignment>
764+
</TableColumnHeader>
765+
</TableHeaders>
766+
<TableRowEntries>
767+
<TableRowEntry>
768+
<TableColumnItems>
769+
<TableColumnItem>
770+
<PropertyName>SelfMemoryPercent</PropertyName>
771+
</TableColumnItem>
772+
<TableColumnItem>
773+
<PropertyName>SelfMemory</PropertyName>
774+
</TableColumnItem>
775+
<TableColumnItem>
776+
<PropertyName>SelfGc</PropertyName>
777+
</TableColumnItem>
778+
<TableColumnItem>
779+
<PropertyName>MemoryPercent</PropertyName>
780+
</TableColumnItem>
781+
<TableColumnItem>
782+
<PropertyName>Memory</PropertyName>
783+
</TableColumnItem>
784+
<TableColumnItem>
785+
<PropertyName>Gc</PropertyName>
786+
</TableColumnItem>
787+
<TableColumnItem>
788+
<PropertyName>Duration</PropertyName>
789+
</TableColumnItem>
790+
<TableColumnItem>
791+
<PropertyName>HitCount</PropertyName>
792+
</TableColumnItem>
793+
<TableColumnItem>
794+
<PropertyName>File</PropertyName>
795+
</TableColumnItem>
796+
<TableColumnItem>
797+
<PropertyName>Line</PropertyName>
798+
</TableColumnItem>
799+
<TableColumnItem>
800+
<PropertyName>Module</PropertyName>
801+
</TableColumnItem>
802+
<TableColumnItem>
803+
<PropertyName>Function</PropertyName>
804+
</TableColumnItem>
805+
<TableColumnItem>
806+
<PropertyName>Text</PropertyName>
807+
</TableColumnItem>
808+
</TableColumnItems>
809+
</TableRowEntry>
810+
</TableRowEntries>
811+
</TableControl>
812+
</View>
612813
</ViewDefinitions>
613814
</Configuration>

Profiler/Profiler.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# for BP to attach
22
if ($PSVersionTable.PSVersion.Major -ge 7) {
3-
[Reflection.Assembly]::LoadFrom("$PSScriptRoot/bin/netstandard2.0/Profiler.dll")
3+
[Reflection.Assembly]::LoadFrom("$PSScriptRoot/bin/net6.0/Profiler.dll")
44
}
55
elseif ($PSVersionTable.PSVersion.Major -ge 5) {
66
[Reflection.Assembly]::LoadFrom("$PSScriptRoot/bin/net452/Profiler.dll")

Profiler/Trace-Script.ps1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,16 @@ function Trace-Script {
164164
# trace starts with event from the measurement script where we enable tracing and ends with event where we disable it
165165
# events are timestamped at the start so user code duration is from the second event (index 1), till the last real event (index -2) where we disable tracing
166166
$total = if ($null -ne $trace -and 0 -lt @($trace).Count) { [TimeSpan]::FromTicks($trace[-2].Timestamp - $trace[2].Timestamp) } else { [TimeSpan]::Zero }
167+
$totalMem = if ($null -ne $trace -and 0 -lt @($trace).Count) { $trace[-2].AllocatedBytes - $trace[2].AllocatedBytes } else { 0 }
167168

168169
Write-Host -ForegroundColor Magenta "Counting averages and percentages for lines." -NoNewline
169170
# this is like SelectMany, it lists all the lines in all files into a single array
170171
$all = foreach ($line in $fileMap.Values.Lines.Values) {
171172
$ticks = if (0 -ne $total.Ticks) { $total.Ticks } else { 1 }
172173
$line.Percent = [Math]::Round($line.Duration.Ticks / $ticks, 5, [System.MidpointRounding]::AwayFromZero) * 100
173174
$line.SelfPercent = [Math]::Round($line.SelfDuration.Ticks / $ticks, 5, [System.MidpointRounding]::AwayFromZero) * 100
175+
$line.MemoryPercent = [Math]::Round($line.Memory / $totalMem, 5, [System.MidpointRounding]::AwayFromZero) * 100
176+
$line.SelfMemoryPercent = [Math]::Round($line.SelfMemory / $totalMem, 5, [System.MidpointRounding]::AwayFromZero) * 100
174177
$line
175178
}
176179
Write-TimeAndRestart $sw
@@ -237,6 +240,22 @@ function Trace-Script {
237240
ForEach-Object { [Profiler.FunctionHitCountView]::new($_) }
238241
Write-TimeAndRestart $sw
239242

243+
Write-Host -ForegroundColor Magenta "Getting Top50 functions with the most Self memory." -NoNewline
244+
$top50SelfMemory = $all |
245+
Where-Object HitCount -gt 0 |
246+
Sort-Object -Property SelfMemory -Descending |
247+
Select-Object -First 50 |
248+
ForEach-Object { [Profiler.SelfMemoryView]::new($_) }
249+
Write-TimeAndRestart $sw
250+
251+
Write-Host -ForegroundColor Magenta "Getting Top50 functions with the most memory." -NoNewline
252+
$top50Memory = $all |
253+
Where-Object HitCount -gt 0 |
254+
Sort-Object -Property Memory -Descending |
255+
Select-Object -First 50 |
256+
ForEach-Object { [Profiler.MemoryView]::new($_) }
257+
Write-TimeAndRestart $sw
258+
240259
# do not use object initializer syntax here @{}
241260
# when it fails it will not create any object
242261
# and won't tell you on which line exactly it failed
@@ -257,6 +276,8 @@ function Trace-Script {
257276
$script:processedTrace.Top50FunctionDuration = $top50FunctionDuration
258277
$script:processedTrace.Top50FunctionHitCount = $top50FunctionHitCount
259278
$script:processedTrace.Top50FunctionSelfDuration = $top50FunctionSelfDuration
279+
$script:processedTrace.Top50SelfMemory = $top50SelfMemory
280+
$script:processedTrace.Top50Memory = $top50Memory
260281

261282
$script:processedTrace
262283

build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ $ErrorActionPreference = "Stop"
77
$sln = "$PSScriptRoot/csharp/Profiler.sln"
88

99
Write-Host "Publish and copy dlls"
10-
$frameworks = "net452", "netstandard2.0"
10+
$frameworks = "net452", "net6.0"
1111
foreach ($framework in $frameworks) {
1212
dotnet publish $sln --framework $framework --configuration $Configuration
1313

csharp/Profiler/CommandHit.cs

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,46 @@
11
using System;
22

3-
namespace Profiler
3+
namespace Profiler;
4+
5+
/// <summary>
6+
/// Represents a command hit on a line
7+
/// </summary>
8+
public class CommandHit
49
{
510
/// <summary>
6-
/// Represents a command hit on a line
11+
/// Line number of the command in the file or ScriptBlock.
12+
/// </summary>
13+
public uint Line { get; set; }
14+
15+
/// <summary>
16+
/// Column of the command in the file or ScriptBlock.
17+
/// </summary>
18+
public uint Column { get; set; }
19+
20+
/// <summary>
21+
/// Number of hits on command.
22+
/// </summary>
23+
public uint HitCount { get; set; } = 1;
24+
25+
/// <summary>
26+
/// Time used exclusively by this command
27+
/// </summary>
28+
public TimeSpan SelfDuration { get; set; }
29+
30+
/// <summary>
31+
/// Command text.
732
/// </summary>
8-
public class CommandHit
33+
public string Text { get; set; }
34+
35+
public CommandHit(Hit hit)
936
{
10-
/// <summary>
11-
/// Line number of the command in the file or scriptblock.
12-
/// </summary>
13-
public uint Line { get; set; }
14-
15-
/// <summary>
16-
/// Column of the command in the file or scriptblock.
17-
/// </summary>
18-
public uint Column { get; set; }
19-
20-
/// <summary>
21-
/// Number of hits on command.
22-
/// </summary>
23-
public uint HitCount { get; set; } = 1;
24-
25-
/// <summary>
26-
/// Time used exclusively by this command
27-
/// </summary>
28-
public TimeSpan SelfDuration { get; set; }
29-
30-
/// <summary>
31-
/// Command text.
32-
/// </summary>
33-
public string Text { get; set; }
34-
35-
public CommandHit(Hit hit)
36-
{
37-
Line = (uint)hit.Line;
38-
Column = (uint)hit.Column;
39-
SelfDuration = hit.SelfDuration;
40-
Text = hit.Text;
41-
}
42-
43-
public override string ToString() {
44-
return $"Profiler.CommandHit: Line={this.Line}; Column={this.Column}; HitCount={this.HitCount}; SelfDuration={this.SelfDuration}; Text='{this.Text}'";
45-
}
37+
Line = (uint)hit.Line;
38+
Column = (uint)hit.Column;
39+
SelfDuration = hit.SelfDuration;
40+
Text = hit.Text;
41+
}
42+
43+
public override string ToString() {
44+
return $"Profiler.CommandHit: Line={this.Line}; Column={this.Column}; HitCount={this.HitCount}; SelfDuration={this.SelfDuration}; Text='{this.Text}'";
4645
}
4746
}

csharp/Profiler/DurationView.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Profiler;
2+
3+
public class DurationView : LineProfileView
4+
{
5+
public DurationView(LineProfile line) : base(line)
6+
{
7+
}
8+
}

0 commit comments

Comments
 (0)