Skip to content

Commit f40bd86

Browse files
committed
Work on parse perf
1 parent 7f2ebd2 commit f40bd86

File tree

1 file changed

+79
-25
lines changed

1 file changed

+79
-25
lines changed

tools/PsesLogAnalyzer/Parse-PsesLog.ps1

+79-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
$peekBuf = $null
33
$currentLineNum = 1
4+
$logEntryNum = 1
45

56
function Parse-PsesLog {
67
param(
@@ -9,24 +10,41 @@ function Parse-PsesLog {
910
[Alias("PSPath")]
1011
[ValidateNotNullOrEmpty()]
1112
[string]
12-
$Path
13+
$Path,
14+
15+
# Hides the progress bar.
16+
[Parameter()]
17+
[switch]
18+
$HideProgress,
19+
20+
# Skips conversion from JSON & storage of the JsonRpc message body which can be large.
21+
[Parameter()]
22+
[switch]
23+
$SkipRpcMessageBody,
24+
25+
[Parameter()]
26+
[switch]
27+
$DebugTimingInfo,
28+
29+
[Parameter()]
30+
[int]
31+
$DebugTimingThresholdMs = 100
1332
)
1433

1534
begin {
16-
1735
# Example log entry start:
1836
# 2018-11-24 12:26:58.302 [DIAGNOSTIC] tid:28 in 'ReadMessage' C:\Users\Keith\GitHub\rkeithhill\PowerShellEditorServices\src\PowerShellEditorServices.Protocol\MessageProtocol\MessageReader.cs:114:
19-
$logEntryRegex =
37+
$logEntryRegex =
2038
[regex]::new(
21-
'(?<ts>[^\[]+)\[(?<lev>([^\]]+))\]\s+tid:(?<tid>\d+)\s+in\s+''(?<meth>\w+)''\s+(?<file>..[^:]+):(?<line>\d+)',
39+
'(?<ts>[^\[]+)\[(?<lev>([^\]]+))\]\s+tid:(?<tid>\d+)\s+in\s+''(?<meth>\w+)''\s+(?<file>..[^:]+):(?<line>\d+)',
2240
[System.Text.RegularExpressions.RegexOptions]::Compiled -bor [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
2341

24-
$filestream =
42+
$filestream =
2543
[System.IO.FileStream]::new(
26-
$Path,
27-
[System.IO.FileMode]:: Open,
28-
[System.IO.FileAccess]::Read,
29-
[System.IO.FileShare]::ReadWrite,
44+
$Path,
45+
[System.IO.FileMode]:: Open,
46+
[System.IO.FileAccess]::Read,
47+
[System.IO.FileShare]::ReadWrite,
3048
4096,
3149
[System.IO.FileOptions]::SequentialScan)
3250

@@ -41,7 +59,7 @@ function Parse-PsesLog {
4159
$line = $streamReader.ReadLine()
4260
}
4361

44-
$script:currentLineNum += 1
62+
$script:currentLineNum++
4563
$line
4664
}
4765

@@ -55,25 +73,42 @@ function Parse-PsesLog {
5573

5674
$line
5775
}
58-
76+
5977
function parseLogEntryStart([string]$line) {
78+
if ($DebugTimingInfo) {
79+
$sw = [System.Diagnostics.Stopwatch]::StartNew()
80+
}
81+
6082
while ($line -notmatch $logEntryRegex) {
6183
Write-Warning "Ignoring line: '$line'"
6284
$line = nextLine
6385
}
64-
86+
87+
if (!$HideProgress -and ($script:logEntryNum % 50 -eq 0)) {
88+
Write-Progress "Processing log entry ${script:logEntryNum} on line: ${script:currentLineNum}"
89+
}
90+
6591
[string]$timestampStr = $matches["ts"]
6692
[DateTime]$timestamp = $timestampStr
6793
[PsesLogLevel]$logLevel = $matches["lev"]
6894
[int]$threadId = $matches["tid"]
6995
[string]$method = $matches["meth"]
7096
[string]$file = $matches["file"]
7197
[int]$lineNumber = $matches["line"]
72-
98+
7399
$message = parseMessage $method
74100

75-
[PsesLogEntry]::new($timestamp, $timestampStr, $logLevel, $threadId, $method, $file, $lineNumber,
101+
[PsesLogEntry]::new($timestamp, $timestampStr, $logLevel, $threadId, $method, $file, $lineNumber,
76102
$message.MessageType, $message.Message)
103+
104+
if ($DebugTimingInfo) {
105+
$sw.Stop()
106+
if ($sw.ElapsedMilliseconds -gt $DebugTimingThresholdMs) {
107+
Write-Warning "Time to parse log entry ${script:logEntryNum} - $($sw.ElapsedMilliseconds) ms"
108+
}
109+
}
110+
111+
$script:logEntryNum++
77112
}
78113

79114
function parseMessage([string]$Method) {
@@ -88,30 +123,30 @@ function Parse-PsesLog {
88123
return $result
89124
}
90125

91-
if (($Method -eq 'ReadMessage') -and
126+
if (($Method -eq 'ReadMessage') -and
92127
($line -match '\s+Received Request ''(?<msg>[^'']+)'' with id (?<id>\d+)')) {
93128
$result.MessageType = [PsesMessageType]::Request
94129
$msg = $matches["msg"]
95130
$id = $matches["id"]
96131
$json = parseJsonMessageBody
97132
$result.Message = [PsesJsonRpcMessage]::new($msg, $id, $json)
98133
}
99-
elseif (($Method -eq 'ReadMessage') -and
134+
elseif (($Method -eq 'ReadMessage') -and
100135
($line -match '\s+Received event ''(?<msg>[^'']+)''')) {
101136
$result.MessageType = [PsesMessageType]::Notification
102137
$msg = $matches["msg"]
103138
$json = parseJsonMessageBody
104139
$result.Message = [PsesNotificationMessage]::new($msg, [PsesNotificationSource]::Client, $json)
105140
}
106-
elseif (($Method -eq 'WriteMessage') -and
141+
elseif (($Method -eq 'WriteMessage') -and
107142
($line -match '\s+Writing Response ''(?<msg>[^'']+)'' with id (?<id>\d+)')) {
108143
$result.MessageType = [PsesMessageType]::Response
109144
$msg = $matches["msg"]
110145
$id = $matches["id"]
111146
$json = parseJsonMessageBody
112147
$result.Message = [PsesJsonRpcMessage]::new($msg, $id, $json)
113148
}
114-
elseif (($Method -eq 'WriteMessage') -and
149+
elseif (($Method -eq 'WriteMessage') -and
115150
($line -match '\s+Writing event ''(?<msg>[^'']+)''')) {
116151
$result.MessageType = [PsesMessageType]::Notification
117152
$msg = $matches["msg"]
@@ -127,35 +162,54 @@ function Parse-PsesLog {
127162
$result
128163
}
129164

130-
function parseMessageBody([string]$startLine = '') {
131-
$result = $startLine
165+
function parseMessageBody([string]$startLine = '', [switch]$Discard) {
166+
if (!$Discard) {
167+
$strBld = [System.Text.StringBuilder]::new($startLine, 4096)
168+
$newLine = "`r`n"
169+
}
170+
132171
try {
133172
while ($true) {
134173
$peekLine = peekLine
135174
if ($null -eq $peekLine) {
136175
break
137176
}
138177

139-
if ($peekLine -match $logEntryRegex) {
178+
if (($peekLine.Length -gt 0) -and ($peekLine[0] -ne ' ') -and ($peekLine -match $logEntryRegex)) {
140179
break
141180
}
142181

143-
$result += (nextLine) + "`r`n"
182+
$nextLine = nextLine
183+
if (!$Discard) {
184+
[void]$strBld.Append($nextLine).Append($newLine)
185+
}
144186
}
145-
146187
}
147188
catch {
148189
Write-Error "Failed parsing message body with error: $_"
149190
}
150191

151-
$result.Trim()
192+
if (!$Discard) {
193+
$msgBody = $strBld.ToString().Trim()
194+
$msgBody
195+
}
196+
else {
197+
$startLine
198+
}
152199
}
153200

154201
function parseJsonMessageBody() {
155202
$obj = $null
156203

157-
try {
204+
if ($SkipRpcMessageBody) {
205+
parseMessageBody -Discard
206+
return $null
207+
}
208+
else {
158209
$result = parseMessageBody
210+
}
211+
212+
try {
159213
$obj = $result.Trim() | ConvertFrom-Json
160214
}
161215
catch {

0 commit comments

Comments
 (0)