Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"servers": {
"Azure MCP Debug Build v0.0.3":{
"type": "stdio",
"command": "C:\\AIR\\fork-ms-mcp\\servers\\Azure.Mcp.Server\\src\\bin\\Debug\\net9.0\\azmcp.exe",
"args": ["server", "start"]
},
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/"
}
}
}
183 changes: 183 additions & 0 deletions cpu-issue-report.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CPU Usage Issue Report</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
padding: 20px;
color: #333;
}
h1, h2, h3 {
color: #0066cc;
}
pre {
background-color: #f5f5f5;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
}
code {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
}
.highlight {
background-color: #ffffcc;
padding: 2px;
}
.comparison {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.code-block {
flex: 1;
min-width: 300px;
}
table {
border-collapse: collapse;
width: 100%;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
</style>
</head>
<body>
<h1>CPU Usage Optimization Report</h1>
<p><strong>Date:</strong> July 16, 2025</p>
<p><strong>Application:</strong> CodeOptimizationsSampleApp</p>

<h2>Executive Summary</h2>
<p>
A significant CPU performance issue was identified in the application. The issue was located in the <code>ReviewValidation.StringValidation</code> method,
specifically in the repeated creation of filtered lists from a large collection of disallowed words. The fix involved implementing a caching mechanism to
avoid repeated filtering and list creation operations, resulting in significant CPU usage reduction.
</p>

<h2>Issue Details</h2>
<h3>Problem Identification</h3>
<p>
The Azure MCP Profiler identified a hotspot in the CPU usage profile of the application. The callstack showed that a significant amount of CPU time
was being spent in the <code>ToList()</code> method called from <code>ReviewValidation.StringValidation</code>. This method was filtering and creating
a new list of disallowed words on every call, despite the source data remaining constant.
</p>

<h3>Profiler Insights</h3>
<table>
<tr>
<th>Issue</th>
<th>CPU Impact</th>
<th>Function</th>
<th>Parent Function</th>
</tr>
<tr>
<td>High CPU Usage</td>
<td>25.39%</td>
<td>Enumerable.ToList</td>
<td>ReviewValidation.StringValidation</td>
</tr>
</table>

<h3>Root Cause Analysis</h3>
<p>
The <code>StringValidation</code> method was filtering a collection of 30,000 disallowed words on every invocation, creating a new list each time.
This was inefficient because:
</p>
<ul>
<li>The source data (<code>DisallowedWords</code>) remains constant throughout the application lifecycle</li>
<li>The filtering criteria is based on <code>CultureInfo</code>, which has a limited set of possible values</li>
<li>The method was called repeatedly in a tight loop in the <code>BackgroundReviewValidation</code> class</li>
</ul>

<h2>Solution Implementation</h2>
<h3>Approach</h3>
<p>
The solution was to implement a caching mechanism for the filtered word lists. A static dictionary was added to store pre-filtered lists for each
culture that has been encountered. This ensures the filtering and list creation operations are performed only once per culture.
</p>

<h3>Code Changes</h3>
<div class="comparison">
<div class="code-block">
<h4>Before:</h4>
<pre><code>public static string StringValidation(string data, char replacementChar, CultureInfo culture)
{
List&lt;string&gt; wordList = DisallowedWords
.Where(word => culture.Equals(CultureInfo.InvariantCulture) || culture.Equals(word.Culture))
.Select(word => word.Text).ToList();

foreach (string word in wordList)
{
data = data.Replace(word, replacementChar.ToString(), ignoreCase: true, culture);
}
return data;
}</code></pre>
</div>
<div class="code-block">
<h4>After:</h4>
<pre><code>// Cache for filtered disallowed word lists by culture to avoid repeated filtering
private static readonly Dictionary&lt;CultureInfo, List&lt;string&gt;&gt; _cultureWordCache = new Dictionary&lt;CultureInfo, List&lt;string&gt;&gt;();

public static string StringValidation(string data, char replacementChar, CultureInfo culture)
{
// Get or create the filtered word list for the specific culture
if (!_cultureWordCache.TryGetValue(culture, out var wordList))
{
// Filter once and cache the result
wordList = DisallowedWords
.Where(word => culture.Equals(CultureInfo.InvariantCulture) || culture.Equals(word.Culture))
.Select(word => word.Text)
.ToList();

_cultureWordCache[culture] = wordList;
}

foreach (string word in wordList)
{
data = data.Replace(word, replacementChar.ToString(), ignoreCase: true, culture);
}
return data;
}</code></pre>
</div>
</div>

<h2>Expected Benefits</h2>
<p>
The implemented solution should provide the following benefits:
</p>
<ul>
<li><strong>Reduced CPU Usage:</strong> By eliminating repeated filtering and list creation operations</li>
<li><strong>Improved Response Time:</strong> Lower CPU usage means faster response times for users</li>
<li><strong>Better Scalability:</strong> The application can handle more concurrent requests with the same resources</li>
<li><strong>Reduced Memory Pressure:</strong> Fewer temporary list allocations means less garbage collection overhead</li>
</ul>

<h2>Additional Recommendations</h2>
<p>
While the current fix addresses the immediate performance bottleneck, here are some additional recommendations for further optimization:
</p>
<ol>
<li>Consider using a more efficient data structure for word lookups, such as a HashSet or Trie</li>
<li>Implement a more efficient string replacement algorithm that doesn't create a new string for each replacement</li>
<li>Evaluate if all 30,000 words need to be loaded into memory at once, or if they could be loaded on demand</li>
<li>Add performance metrics and monitoring to detect similar issues in the future</li>
</ol>

<hr>
<p><em>Report generated on July 16, 2025</em></p>
</body>
</html>
21 changes: 21 additions & 0 deletions prompts/fix-top-cpu-issue-by-padawan.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
mode: 'agent'
tools: ['codebase', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'terminalSelection', 'terminalLastCommand', 'openSimpleBrowser', 'fetch', 'findTestFiles', 'searchResults', 'githubRepo', 'extensions', 'runTests', 'editFiles', 'runNotebooks', 'search', 'new', 'runCommands', 'runTasks', 'applicationinsights']
---

You are a developer working on a ASP.NET Core project. The source code is located in the `src` directory of the app.

The GitHub repo has an agent to work on improving code. It needs as much details for the issue as possible, like issue descriptions, callstacks and so on.

Can you query the top CPU related code optimization insights, and create a github issue so that it can be fixed by the github coding agent?

Here are some additional context to help you with the task:

## Inputs

Query the insights from the Azure MCP Profiler using the following parameters:

- Subscription: Service Profiler Development
- App Id: 94adcdae-2d1b-4c68-9c1f-42d876be4c2c
- Time Range: Last 24 hours

27 changes: 27 additions & 0 deletions prompts/fix-top-cpu-issue.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
mode: 'agent'
tools: ['editFiles', 'runNotebooks', 'search', 'new', 'runCommands', 'runTasks', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'openSimpleBrowser', 'fetch', 'githubRepo', 'extensions', 'runTests', 'applicationinsights']
---

You are a developer working on a ASP.NET Core project. The source code is located in the `src` directory of the app.

You are tasked to figure out the top CPU usage issue in the app and fix it.

You will find the code optimization insights in the Azure MCP applicationinsights codeoptimizations. You will use the `applicationinsights` tool to list all code optimization insights for the app.

Once you have the insights, you will analyze the code and identify the top CPU usage issue. You will then use the `editFiles` tool to make the necessary changes to the code. Note that the code change should based on the callstack provided in the insights.

Also, concentrate on the performance fix. Do not change the functionality of the code, and do not try to fix any other issues that are not related to CPU usage.

Generate a report at the end of the task and save it to a file named `cpu-issue-report.html` in the root directory of the app.

Here are some additional context to help you with the task:

## Inputs

Query the insights from the Azure MCP Profiler using the following parameters:

- Subscription: Service Profiler Development
- Resource Group: eshop-demo
- Time Range: Last 24 hours

20 changes: 20 additions & 0 deletions prompts/list-codeopt.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'extensions', 'fetch', 'findTestFiles', 'githubRepo', 'new', 'openSimpleBrowser', 'problems', 'readCellOutput', 'runCommands', 'runNotebooks', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure', 'updateUserPreferences', 'usages', 'vscodeAPI', 'Azure MCP Debug Build v0.0.2', 'azmcp-profiler-list-insights']
---

Read through the following instructions thoroughly first.

## Inputs

Subscription: Service Profiler Development
App Id: 94adcdae-2d1b-4c68-9c1f-42d876be4c2c
Time Range: Last 24 hours

## Actions

List all my code optimization insights for the app.

## Notes

The source code in the callstack locates in the `src` directory of the app.
17 changes: 14 additions & 3 deletions src/Reviews/ReviewValidation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,22 @@ internal record LocalizedWord(string Text, CultureInfo Culture);

private static IEnumerable<LocalizedWord> DisallowedWords { get; } = ReviewHelper.LoadDisallowedWords();

// Cache for filtered disallowed word lists by culture to avoid repeated filtering
private static readonly Dictionary<CultureInfo, List<string>> _cultureWordCache = new Dictionary<CultureInfo, List<string>>();

public static string StringValidation(string data, char replacementChar, CultureInfo culture)
{
List<string> wordList = DisallowedWords
.Where(word => culture.Equals(CultureInfo.InvariantCulture) || culture.Equals(word.Culture))
.Select(word => word.Text).ToList();
// Get or create the filtered word list for the specific culture
if (!_cultureWordCache.TryGetValue(culture, out var wordList))
{
// Filter once and cache the result
wordList = DisallowedWords
.Where(word => culture.Equals(CultureInfo.InvariantCulture) || culture.Equals(word.Culture))
.Select(word => word.Text)
.ToList();

_cultureWordCache[culture] = wordList;
}

foreach (string word in wordList)
{
Expand Down