diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 0000000..413529d --- /dev/null +++ b/.vscode/mcp.json @@ -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/" + } + } +} \ No newline at end of file diff --git a/cpu-issue-report.html b/cpu-issue-report.html new file mode 100644 index 0000000..b4131ea --- /dev/null +++ b/cpu-issue-report.html @@ -0,0 +1,183 @@ + + + + + + CPU Usage Issue Report + + + +

CPU Usage Optimization Report

+

Date: July 16, 2025

+

Application: CodeOptimizationsSampleApp

+ +

Executive Summary

+

+ A significant CPU performance issue was identified in the application. The issue was located in the ReviewValidation.StringValidation 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. +

+ +

Issue Details

+

Problem Identification

+

+ 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 ToList() method called from ReviewValidation.StringValidation. This method was filtering and creating + a new list of disallowed words on every call, despite the source data remaining constant. +

+ +

Profiler Insights

+ + + + + + + + + + + + + +
IssueCPU ImpactFunctionParent Function
High CPU Usage25.39%Enumerable.ToListReviewValidation.StringValidation
+ +

Root Cause Analysis

+

+ The StringValidation method was filtering a collection of 30,000 disallowed words on every invocation, creating a new list each time. + This was inefficient because: +

+ + +

Solution Implementation

+

Approach

+

+ 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. +

+ +

Code Changes

+
+
+

Before:

+
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();
+
+    foreach (string word in wordList)
+    {
+        data = data.Replace(word, replacementChar.ToString(), ignoreCase: true, culture);
+    }
+    return data;
+}
+
+
+

After:

+
// 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)
+{
+    // 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;
+}
+
+
+ +

Expected Benefits

+

+ The implemented solution should provide the following benefits: +

+ + +

Additional Recommendations

+

+ While the current fix addresses the immediate performance bottleneck, here are some additional recommendations for further optimization: +

+
    +
  1. Consider using a more efficient data structure for word lookups, such as a HashSet or Trie
  2. +
  3. Implement a more efficient string replacement algorithm that doesn't create a new string for each replacement
  4. +
  5. Evaluate if all 30,000 words need to be loaded into memory at once, or if they could be loaded on demand
  6. +
  7. Add performance metrics and monitoring to detect similar issues in the future
  8. +
+ +
+

Report generated on July 16, 2025

+ + diff --git a/prompts/fix-top-cpu-issue-by-padawan.prompt.md b/prompts/fix-top-cpu-issue-by-padawan.prompt.md new file mode 100644 index 0000000..2e4fcf3 --- /dev/null +++ b/prompts/fix-top-cpu-issue-by-padawan.prompt.md @@ -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 + diff --git a/prompts/fix-top-cpu-issue.prompt.md b/prompts/fix-top-cpu-issue.prompt.md new file mode 100644 index 0000000..ee7f5fb --- /dev/null +++ b/prompts/fix-top-cpu-issue.prompt.md @@ -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 + diff --git a/prompts/list-codeopt.prompt.md b/prompts/list-codeopt.prompt.md new file mode 100644 index 0000000..fd1130e --- /dev/null +++ b/prompts/list-codeopt.prompt.md @@ -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. diff --git a/src/Reviews/ReviewValidation.cs b/src/Reviews/ReviewValidation.cs index 18e3a01..0226a21 100644 --- a/src/Reviews/ReviewValidation.cs +++ b/src/Reviews/ReviewValidation.cs @@ -8,11 +8,22 @@ internal record LocalizedWord(string Text, CultureInfo Culture); private static IEnumerable DisallowedWords { get; } = ReviewHelper.LoadDisallowedWords(); + // Cache for filtered disallowed word lists by culture to avoid repeated filtering + private static readonly Dictionary> _cultureWordCache = new Dictionary>(); + public static string StringValidation(string data, char replacementChar, CultureInfo culture) { - List 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) {