Skip to content

Commit 8dc602a

Browse files
committed
Show memory in megabytes
1 parent 0066ca7 commit 8dc602a

16 files changed

+83
-63
lines changed

Profiler/Profiler.Format.ps1xml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,20 @@
1111
<ListEntry>
1212
<ListItems>
1313
<ListItem>
14-
<Label>Top50Duration</Label>
15-
<ScriptBlock>'List top 50 lines based on duration'</ScriptBlock>
14+
<Label>Top50SelfDuration</Label>
15+
<ScriptBlock>'List top 50 lines based on time consumed directly by the line'</ScriptBlock>
16+
</ListItem>
17+
<ListItem>
18+
<Label>Top50SelfMemory</Label>
19+
<ScriptBlock>'List top 50 lines based on the memory consumed directly by the line'</ScriptBlock>
1620
</ListItem>
1721
<ListItem>
1822
<Label>Top50HitCount</Label>
1923
<ScriptBlock>'List top 50 lines based on hit count'</ScriptBlock>
2024
</ListItem>
2125
<ListItem>
22-
<Label>Top50SelfDuration</Label>
23-
<ScriptBlock>'List top 50 lines based on time consumed directly by the line'</ScriptBlock>
26+
<Label>Top50Duration</Label>
27+
<ScriptBlock>'List top 50 lines based on duration'</ScriptBlock>
2428
</ListItem>
2529
<ListItem>
2630
<Label>Top50FunctionDuration</Label>
@@ -38,10 +42,6 @@
3842
<Label>Top50Memory</Label>
3943
<ScriptBlock>'List top 50 lines based on the memory consumed'</ScriptBlock>
4044
</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>
4545
<ListItem>
4646
<Label>AllLines</Label>
4747
<ScriptBlock>'Show all lines processed by profiler trace'</ScriptBlock>
@@ -56,6 +56,9 @@
5656
<ListItem>
5757
<PropertyName>StopwatchDuration</PropertyName>
5858
</ListItem>
59+
<ListItem>
60+
<PropertyName>ScriptBlock</PropertyName>
61+
</ListItem>
5962
</ListItems>
6063
</ListEntry>
6164
</ListEntries>

Profiler/Profiler.psd1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
RootModule = 'Profiler.psm1'
99

1010
# Version number of this module.
11-
ModuleVersion = '4.2.0'
11+
ModuleVersion = '4.3.0'
1212

1313
# Supported PSEditions
1414
# CompatiblePSEditions = @()
@@ -26,10 +26,10 @@ CompanyName = 'nohwnd'
2626
Copyright = '(c) nohwnd. All rights reserved.'
2727

2828
# Description of the functionality provided by this module
29-
Description = 'Script, ScriptBlock and module performance profiler for PowerShell 5, and PowerShell 7.'
29+
Description = 'Script, ScriptBlock and module performance profiler for PowerShell 5.1, and PowerShell 7.'
3030

3131
# Minimum version of the PowerShell engine required by this module
32-
PowerShellVersion = '5.0.0'
32+
PowerShellVersion = '5.1.0'
3333

3434
# Name of the PowerShell host required by this module
3535
# PowerShellHostName = ''

Profiler/Trace-Script.ps1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function Trace-Script {
143143
$trace = $result.Trace
144144

145145
$scriptBlocks = $out.ScriptBlocks
146-
$traceCount = $trace.Count
146+
$traceCount = $trace.Count-4 # 2 first and 2 last events are internal events of Profiler
147147

148148
Write-Host -ForegroundColor Magenta "Processing $($traceCount) trace events. $(if (1000000 -lt $traceCount) { "This might take a while..."})"
149149

@@ -174,6 +174,8 @@ function Trace-Script {
174174
$line.SelfPercent = [Math]::Round($line.SelfDuration.Ticks / $ticks, 5, [System.MidpointRounding]::AwayFromZero) * 100
175175
$line.MemoryPercent = if (0 -ne $totalMem) { [Math]::Round($line.Memory / $totalMem, 5, [System.MidpointRounding]::AwayFromZero) * 100 } else { 100 }
176176
$line.SelfMemoryPercent = if (0 -ne $totalMem) { [Math]::Round($line.SelfMemory / $totalMem, 5, [System.MidpointRounding]::AwayFromZero) * 100 } else { 100 }
177+
$line.Memory = [Math]::Round($line.Memory, 5, [System.MidpointRounding]::AwayFromZero)
178+
$line.SelfMemory = [Math]::Round($line.SelfMemory, 5, [System.MidpointRounding]::AwayFromZero)
177179
$line
178180
}
179181
Write-TimeAndRestart $sw
@@ -266,6 +268,7 @@ function Trace-Script {
266268
# this way we can get the partial object out for
267269
# debugging when this fails on someones system
268270
$script:processedTrace = [Profiler.Trace]::new()
271+
$script:processedTrace.ScriptBlock = $ScriptBlock
269272
$script:processedTrace.TotalDuration = $total
270273
$script:processedTrace.StopwatchDuration = $out.Stopwatch
271274
$script:processedTrace.Events = $trace

Profiler/Trace-ScriptInternal.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ function Trace-ScriptInternal {
6464

6565
$out.Stopwatch = $result.Stopwatch
6666
$out.ScriptBlocks = $result.ScriptBlocks
67-
Write-Host -Foreground Magenta "Tracing done. Got $($trace.Count) trace events."
67+
$traceCount = $result.Trace.Count - 4 # 2 first and 2 last events are internal events of Profiler
68+
Write-Host -Foreground Magenta "Tracing done. Got $($traceCount) trace events."
6869
$result
6970
}
7071

csharp/Profiler/CommandHit.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ public class CommandHit
1010
/// <summary>
1111
/// Line number of the command in the file or ScriptBlock.
1212
/// </summary>
13-
public uint Line { get; set; }
13+
public int Line { get; set; }
1414

1515
/// <summary>
1616
/// Column of the command in the file or ScriptBlock.
1717
/// </summary>
18-
public uint Column { get; set; }
18+
public int Column { get; set; }
1919

2020
/// <summary>
2121
/// Number of hits on command.
2222
/// </summary>
23-
public uint HitCount { get; set; } = 1;
23+
public int HitCount { get; set; } = 1;
2424

2525
/// <summary>
2626
/// Time used exclusively by this command
@@ -34,8 +34,8 @@ public class CommandHit
3434

3535
public CommandHit(Hit hit)
3636
{
37-
Line = (uint)hit.Line;
38-
Column = (uint)hit.Column;
37+
Line = (int)hit.Line;
38+
Column = (int)hit.Column;
3939
SelfDuration = hit.SelfDuration;
4040
Text = hit.Text;
4141
}

csharp/Profiler/Hit.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,23 @@ public struct Hit
8585

8686
public bool Folded;
8787

88-
// HeapSize at the start of the hit.
89-
public long HeapSize;
88+
// HeapSize at the start of the hit in MB.
89+
public decimal HeapSize;
9090

91-
// WorkingSet at the start of the hit.
92-
public long WorkingSet;
91+
// WorkingSet at the start of the hit in MB.
92+
public decimal WorkingSet;
9393

94-
// HeapSize heapSize consumed by the hit (endHeapSize - startHeapSize).
95-
public long SelfHeapSize;
94+
// HeapSize heapSize consumed by the hit (endHeapSize - startHeapSize) in MB.
95+
public decimal SelfHeapSize;
9696

97-
// Working set consumed by the hit.
98-
public long SelfWorkingSet;
97+
// Working set consumed by the hit in MB.
98+
public decimal SelfWorkingSet;
9999

100-
// Working set consumed by the hit.
101-
public long AllocatedBytes;
100+
// Working set consumed by the hit in MB.
101+
public decimal AllocatedBytes;
102102

103-
public long SelfAllocatedBytes;
103+
// Bytes allocated by this hit in MB.
104+
public decimal SelfAllocatedBytes;
104105

105106
public int Gc0;
106107
public int SelfGc0;
@@ -112,6 +113,6 @@ public struct Hit
112113
public int SelfGc2;
113114

114115

115-
public long TotalBytes;
116+
public decimal TotalBytes;
116117
public int TotalGc;
117118
}

csharp/Profiler/LineProfile.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class LineProfile
1111
/// <summary>
1212
/// Percent of total duration used by line including all the code it calls.
1313
/// </summary>
14-
public double Percent { get; set; } = 0.00;
14+
public decimal Percent { get; set; } = 0;
1515

1616
/// <summary>
1717
/// Time used by line including subcalls.
@@ -22,7 +22,7 @@ public class LineProfile
2222
/// <summary>
2323
/// Percent of total duration used by line, excluding the code it calls.
2424
/// </summary>
25-
public double SelfPercent { get; set; } = 0.00;
25+
public decimal SelfPercent { get; set; } = 0;
2626

2727
/// <summary>
2828
/// Time used exclusively by this line.
@@ -33,22 +33,22 @@ public class LineProfile
3333
/// <summary>
3434
/// Percent of total memory used by line including all the code it calls.
3535
/// </summary>
36-
public double MemoryPercent { get; set; } = 0.00;
36+
public decimal MemoryPercent { get; set; } = 0;
3737

3838
/// <summary>
3939
/// Memory consumed by line and all subcalls.
4040
/// </summary>
41-
public long Memory { get; set; }
41+
public decimal Memory { get; set; }
4242

4343
/// <summary>
4444
/// Percent of total memory used by line, excluding the code it calls.
4545
/// </summary>
46-
public double SelfMemoryPercent { get; set; } = 0.00;
46+
public decimal SelfMemoryPercent { get; set; } = 0;
4747

4848
/// <summary>
4949
/// Memory consumed exclusively by this line.
5050
/// </summary>
51-
public long SelfMemory { get; set; }
51+
public decimal SelfMemory { get; set; }
5252

5353
/// <summary>
5454
/// Garbage collections happening on this line and in all subcalls (all generations).
@@ -64,7 +64,7 @@ public class LineProfile
6464
/// <summary>
6565
/// Number of hits on line.
6666
/// </summary>
67-
public uint HitCount { get; set; } = 0;
67+
public int HitCount { get; set; } = 0;
6868

6969
/// <summary>
7070
/// Name of file or id of ScriptBlock the line belongs to.
@@ -74,7 +74,7 @@ public class LineProfile
7474
/// <summary>
7575
/// Line number in the file or ScriptBlock.
7676
/// </summary>
77-
public uint? Line { get; set; }
77+
public int? Line { get; set; }
7878

7979
/// <summary>
8080
/// Function that called this line.
@@ -104,5 +104,5 @@ public class LineProfile
104104
/// <summary>
105105
/// All command hits in this line using column as key.
106106
/// </summary>
107-
public IDictionary<uint, CommandHit> CommandHits { get; set; } = new Dictionary<uint, CommandHit>();
107+
public IDictionary<int, CommandHit> CommandHits { get; set; } = new Dictionary<int, CommandHit>();
108108
}

csharp/Profiler/LineProfileView.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public LineProfileView(LineProfile line)
2424
/// <summary>
2525
/// Percent of total duration used by line including all the code it calls.
2626
/// </summary>
27-
public double Percent => _line.Percent;
27+
public decimal Percent => _line.Percent;
2828

2929
/// <summary>
3030
/// Time used by line including subcalls.
@@ -35,7 +35,7 @@ public LineProfileView(LineProfile line)
3535
/// <summary>
3636
/// Percent of total duration used by line, excluding the code it calls.
3737
/// </summary>
38-
public double SelfPercent => _line.SelfPercent;
38+
public decimal SelfPercent => _line.SelfPercent;
3939

4040
/// <summary>
4141
/// Time used exclusively by this line.
@@ -45,22 +45,22 @@ public LineProfileView(LineProfile line)
4545
/// <summary>
4646
/// Percent of total memory used by line including all the code it calls.
4747
/// </summary>
48-
public double MemoryPercent => _line.MemoryPercent;
48+
public decimal MemoryPercent => _line.MemoryPercent;
4949

5050
/// <summary>
5151
/// Memory used by this line.
5252
/// </summary>
53-
public long Memory => _line.Memory;
53+
public decimal Memory => _line.Memory;
5454

5555
/// <summary>
5656
/// Percent of total memory used by line.
5757
/// </summary>
58-
public double SelfMemoryPercent => _line.SelfMemoryPercent;
58+
public decimal SelfMemoryPercent => _line.SelfMemoryPercent;
5959

6060
/// <summary>
6161
/// Memory used exclusively by this line.
6262
/// </summary>
63-
public long SelfMemory => _line.SelfMemory;
63+
public decimal SelfMemory => _line.SelfMemory;
6464

6565
/// <summary>
6666
/// Garbage collection count that happened on this line.
@@ -77,7 +77,7 @@ public LineProfileView(LineProfile line)
7777
/// <summary>
7878
/// Number of hits on line.
7979
/// </summary>
80-
public uint HitCount => _line.HitCount;
80+
public int HitCount => _line.HitCount;
8181

8282
/// <summary>
8383
/// Name of file or id of ScriptBlock the line belongs to.
@@ -87,7 +87,7 @@ public LineProfileView(LineProfile line)
8787
/// <summary>
8888
/// Line number in the file or ScriptBlock.
8989
/// </summary>
90-
public uint? Line => _line.Line;
90+
public int? Line => _line.Line;
9191

9292
/// <summary>
9393
/// Function that called this line.
@@ -117,5 +117,5 @@ public LineProfileView(LineProfile line)
117117
/// <summary>
118118
/// All command hits in this line using column as key.
119119
/// </summary>
120-
public IDictionary<uint, CommandHit> CommandHits => _line.CommandHits;
120+
public IDictionary<int, CommandHit> CommandHits => _line.CommandHits;
121121
}

csharp/Profiler/ProfilerTracer.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,20 @@ public class ProfilerTracer : ITracer
4646
// timespan ticks are 10k per millisecond, but the stopwatch can have different resolution
4747
// calculate the diff between the timestamps and convert it to 10k per ms ticks
4848
//
49-
// cast the frequency to double to avoid whole number division. On systems where frequency
49+
// cast the frequency to decimal to avoid whole number division. On systems where frequency
5050
// is smaller than ticks per second this otherwise results in 0, and all timestamps then
5151
// become positive infinity because of timestamp / 0 = ∞ or when cast to long: -9223372036854775808
52-
private static double _tickDivider = ((double)Stopwatch.Frequency) / TimeSpan.TicksPerSecond;
52+
private static decimal _tickDivider = ((decimal)Stopwatch.Frequency) / TimeSpan.TicksPerSecond;
5353
private const string ScriptBlockName = "<ScriptBlock>";
54+
private readonly bool _usePreciseMemoryMeasurement;
5455
internal int _index = 0;
5556
internal Hit _previousHit;
57+
internal readonly decimal _megaByte = 1024 * 1024;
58+
59+
public ProfilerTracer()
60+
{
61+
_usePreciseMemoryMeasurement = Environment.GetEnvironmentVariable("POWERSHELL_PROFILER_PRECISE_MEMORY_MEASUREMENT") == "1";
62+
}
5663

5764
public List<Hit> Hits { get; } = new List<Hit>();
5865
public Dictionary<Guid, ScriptBlock> ScriptBlocks { get; } = new Dictionary<Guid, ScriptBlock>();
@@ -75,9 +82,9 @@ public void Trace(string _, IScriptExtent extent, ScriptBlock scriptBlock, int l
7582
var gc2 = GC.CollectionCount(2);
7683

7784
#if NET5_0_OR_GREATER
78-
var allocatedBytes = GC.GetTotalAllocatedBytes(precise: false);
85+
var allocatedBytes = GC.GetTotalAllocatedBytes(precise: _usePreciseMemoryMeasurement) / _megaByte;
7986
#else
80-
var allocatedBytes = GC.GetTotalMemory(forceFullCollection: false);
87+
var allocatedBytes = GC.GetTotalMemory(forceFullCollection: false) / _megaByte;
8188
#endif
8289

8390
// we are using structs so we need to insert the final struct to the
@@ -144,7 +151,7 @@ public void Trace(string _, IScriptExtent extent, ScriptBlock scriptBlock, int l
144151
}
145152

146153
private void SetSelfValuesAndAddToHits(ref Hit eventRecord, long timestamp,
147-
long workingSet, long heapSize, long allocatedBytes,
154+
decimal workingSet, decimal heapSize, decimal allocatedBytes,
148155
int gc0, int gc1, int gc2)
149156
{
150157
eventRecord.SelfWorkingSet = workingSet - eventRecord.WorkingSet;

csharp/Profiler/Profiler_ProcessFunctions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ public static Dictionary<string, LineProfile> ProcessFunctions(List<Hit> trace)
8787
// on the same line so we can see which commands contributed to the line duration
8888
//if we need to count duration we can do it by moving this to the next part of the code
8989
// where we process each hit on the line
90-
if (!lineProfile.CommandHits.TryGetValue((uint)hit.Column, out var commandHit))
90+
if (!lineProfile.CommandHits.TryGetValue((int)hit.Column, out var commandHit))
9191
{
9292
commandHit = new CommandHit(hit);
93-
lineProfile.CommandHits.Add((uint)hit.Column, commandHit);
93+
lineProfile.CommandHits.Add((int)hit.Column, commandHit);
9494
}
9595
else
9696
{

csharp/Profiler/Profiler_ProcessLines.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public static Dictionary<Guid, File> ProcessLines(List<Hit> trace, Dictionary<Gu
7171
lineProfile = new LineProfile
7272
{
7373
File = file.Name,
74-
Line = (uint)lineNumber,
74+
Line = (int)lineNumber,
7575
Text = text,
7676
Function = hit.Function,
7777
Module = hit.Module,
@@ -141,10 +141,10 @@ public static Dictionary<Guid, File> ProcessLines(List<Hit> trace, Dictionary<Gu
141141
// on the same line so we can see which commands contributed to the line duration
142142
// if we need to count duration we can do it by moving this to the next part of the code
143143
// where we process each hit on the line
144-
if (!lineProfile.CommandHits.TryGetValue((uint)hit.Column, out var commandHit))
144+
if (!lineProfile.CommandHits.TryGetValue((int)hit.Column, out var commandHit))
145145
{
146146
commandHit = new CommandHit(hit);
147-
lineProfile.CommandHits.Add((uint)hit.Column, commandHit);
147+
lineProfile.CommandHits.Add((int)hit.Column, commandHit);
148148
}
149149
else
150150
{

0 commit comments

Comments
 (0)