Wrap around the New-MpPerformanceRecording
Why Defender Boys decided to build Invoke-DBDefenderPerformance powershell tool

When you run into performance issues on a Windows endpoint, Microsoft Defender is sometimes part of the conversation.
So why does this happen?
It usually falls back to the fact that modern environments are messy:
- legacy applications
- developer tooling
- self-updating binaries
- temporary execution paths
- unsigned components
The Reality of Modern Endpoint Protection
Microsoft Defender today is far more than traditional antivirus.
It includes:
- real-time protection
- behavioral monitoring
- Endpoint Detection & Response (EDR, and if you are looking at all workloads such as identity, data etc we have XDR)
- script and memory inspection
- integration with cloud intelligence
All of this is designed to handle both:
- modern threats
- and older, less predictable software
That combination is important. Because in many environments, the biggest performance impact doesn’t come from malware – it comes from:
- complex applications
- heavy file churn
- development workloads
- installers and updaters
- or software that doesn’t follow modern best practices
Where Things Get Difficult
From a troubleshooting perspective, this creates a challenge.
You might see:
- CPU spikes in MsMpEng.exe
- activity from MsSense.exe
- delays during file operations
But that doesn’t tell you:
- which files are being scanned
- why they are being scanned
- which process triggered the activity
- or how expensive the scans actually are
Without that visibility, it’s easy to fall into guesswork.
What Microsoft Provides
Microsoft provides built-in tooling for this:
- New-MpPerformanceRecording
- Get-MpPerformanceReport
Which allow you to capture:
- detailed scan activity
- durations
- top files and processes
- scan reasons (like EDRSensor)
The data is there but the format is not very easy to interpret for everyone
- timestamps are not human-readable
- durations are in ticks
- output is deeply nested
- there’s no prioritization
So while everything you need is technically there, it still takes effort to interpret.
Bridging the Gap
That’s where these functions come in:
- Invoke-DBDefenderPerformance
- Convert-DBDefenderPerformanceReport
The idea is simple, take Defender’s detailed trace data and make it usable for real-world analysis. Instead of manually parsing JSON, you get:
- normalized timings (milliseconds instead of ticks)
- clear overview of scan activity
- grouped insights by:
- scan reason
- file type
- path
- visibility into what’s actually consuming time
This makes it easier to answer questions like:
- Is this driven by AV scanning or EDR activity?
- Are specific file types more expensive?
- Are certain paths generating excessive activity?
- Is this expected behavior for the workload?
- Why This Matters
In many cases, Defender is working exactly as intended but it has to operate in environments where:
- software may be outdated
- files change frequently
- large numbers of small files are accessed
- or applications behave in ways that trigger deeper inspection
Without proper analysis, it’s easy to jump straight to exclusions. That approach can work – but could introduce risks.
A better approach is:
- Understand what’s happening
- Identify the actual cost drivers
- Decide whether tuning is necessary
A typical trace might show:
- OnDemandScan activity
- Reason: EDRSensor
- Files under:
- AppData\Local\Programs\Microsoft VS Code
- node_modules
- Process-based scans (pid:xxxxx)
Defender is simply doing its job – inspecting what could be risky.
The Goal
The purpose of these functions isn’t to reduce protection. It’s to provide clarity. Because once you can see:
- what is being scanned
- why it’s being scanned
- and how much it costs
The tool is published in the following Github repo:
https://github.com/mattiasborg82/PublicTools/blob/main/Defender%20Boys/Defender/Performance/Invoke-DBDefenderPerformance.ps1
Example usage to Create a recording:
Invoke-DBDefenderPerformance -Seconds 900 -Top 50 -Raw -ExportJson

Example usage to Read the report:
$report = Get-MpPerformanceReport -Path "C:\Temp\DefenderPerformance-20260428-095235.etl" -Raw
$summary = Convert-DBDefenderPerformanceReport -Report $report -Top 10 -SlowScanMs 200 -IncludeRaw
$summary | Format-Table -AutoSize
$summary.SlowScans | Format-Table DurationMs, ScanType, Reason, SkipReason, Extension, Path -AutoSize
$summary.ByReason | Format-Table -AutoSize
$summary.ByExtension | Format-Table -AutoSize
$summary.ByParentPath | Format-Table -AutoSize
$summary.SlowScans |
Where-Object Reason -eq "EDRSensor" |
Select-Object DurationMs, ScanType, Extension, Path |
Format-Table -AutoSize
# Additional analysis example: Check authenticode signatures of slow scans involving executables
$summary.SlowScans |
Where-Object { $_.Extension -in ".exe", ".dll" } |
Select-Object -ExpandProperty Path -Unique |
ForEach-Object {
if (Test-Path -LiteralPath $_) {
Get-AuthenticodeSignature -FilePath $_ |
Select-Object Path, Status, StatusMessage, SignerCertificate
}
}

Basically, you can now make well-informed decisions in a easy way
#Happy Hunting













