惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
Recent Announcements
Recent Announcements
B
Blog
D
Docker
V
V2EX
GbyAI
GbyAI
L
LangChain Blog
博客园 - Franky
U
Unit 42
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
博客园 - 【当耐特】
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
博客园_首页
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
量子位
Blog — PlanetScale
Blog — PlanetScale
罗磊的独立博客

博客园 - MeteorSeed

【译】借助 Visual Studio 订阅权益 Cloud Academy 更快掌握 Azure 技能 【译】告知您的模型何时需要进行深度思考 【译】Visual Studio 七月更新 —— 认识全新智能体,由 GitHub Copilot SDK 提供技术支持 【译】Visual Studio 管理员?快来参与我们的私有市场预览版体验! 【译】挑选、管理并充分发挥你的模型 【译】内置 Agent Skill 将 .NET 与 Azure 专业能力引入 Visual Studio 【译】Visual Studio 开发、测试权益:在 Azure 中自由构建、测试与开展实验 【译】Visual Studio 六月更新 —— 追踪使用情况,信赖你的工具 【译】利用 GitHub Actions 实现 Visual Studio 扩展构建自动化 【译】自定义 Visual Studio 的界面外观 【译】无需离开 Visual Studio 即可审阅拉取请求 【译】Visual Studio 五月更新 —— 计划、评审、优化 【译】构建前先计划:带你了解 Visual Studio 中的 Plan Agent 【译】Visual Studio 中的 Agent Skill:让 Copilot 适配团队工作模式 【译】TypeScript 7 测试版已在 Visual Studio 2026 18.6 Insiders 3 中默认启用 【译】Visual Studio 四月更新 —— Cloud Agent 集成 【译】Azure MCP 工具现已内置集成至 Visual Studio 2022,无需额外安装扩展 【译】告别繁琐查错:认识下新的 Visual Studio Debugger Agent Workflow 【译】在 Visual Studio 中完全掌控您的悬浮窗口 【译】Bookmark Studio:在 Visual Studio 中实现书签功能升级 【译】Visual Studio 三月更新 —— 打造专属自定义 Agent 本地大模型部署全攻略:从 0 到 1 玩转 Ollama 【译】让开发流程更高效:为 Visual Studio 订阅用户解锁 Syncfusion 【译】第一时间获取 Visual Studio 订阅的独家资讯,直达您的收件箱 【译】Visual Studio Dev Essentials:面向每位开发者的免费实用工具 【译】Visual Studio 二月更新 【译】Visual Studio 中的 Agent:内置 Agent 和自定义 Agent 【译】Visual Studio 一月更新 —— 增强的编辑器体验 【MongoDB】MongoDB 概述 【译】Copilot 记忆
【译】Copilot Profiler Agent —— 分析任务交由 AI,应用性能...
MeteorSeed · 2026-01-04 · via 博客园 - MeteorSeed

  在 Visual Studio 2026 中,我们推出了 Copilot Profiler Agent,这是一款新的人工智能驱动的助手,可帮助您分析和优化代码中的性能瓶颈。通过将 GitHub Copilot 的功能与 Visual Studio 的性能分析器相结合,您现在可以用自然语言询问有关性能的问题,深入了解热点路径,并快速发现优化机会。让我们来看一个真实的例子,了解这款工具如何帮助您实现有意义的性能改进。

对实际项目进行基准测试

  为了展示 Copilot Profiler Agent 的功能,让我们对一个广受欢迎的开源项目 CsvHelper 进行优化。您可以按照以下步骤操作:克隆我的代码仓库分支,然后通过“git checkout 435ff7c”命令切换到我修复之前的版本,我们将在下文详细介绍该修复。

  在我之前的一篇博客文章中,我添加了一个 CsvHelper.Benchmarks 项目,其中包含一个用于读取 CSV 记录的基准测试。这次我想看看我们是否可以优化 CSV 记录的写入。通常,我会通过为想要优化的代码创建基准测试来开始这项研究,不过虽然我们仍然会这样做,但我们可以让 Copilot 来承担这些繁重的工作。在 Copilot 聊天窗口中,我可以问@Profiler “帮我为 #WriteRecords 方法编写一个基准测试”。@Profiler 让我们直接与 Copilot Profiler Agent 对话,而 #WriteRecords 则明确告诉它我们要进行基准测试的方法。

1

  从这里开始,Copilot 着手创建我们的新基准测试,它会询问我们是否可以安装分析器的 NuGet 包,以便在运行基准测试时从中提取信息。它还会根据找到的任何现有基准测试来构建新的基准测试模型,因此生成的基准测试与我们已经编写的非常相似,从而保持与存储库风格的一致性。最后,它会启动构建过程,以确保一切正常。

2

  完成后,它会提供一些有用的后续提示来启动调查。我们可以点击其中一个来展开调查,不过我想对基准测试做些细微的修改。

3

  我对基准测试做了些调整,增加了几个供我们写入的字段,这里具体是 2 个整数字段和 2 个字符串字段。在为这篇博客撰写内容之前,我最初让 Copilot 来做这件事时,它每次都是写入一个新的内存流,而不是同一个内存流。写入同一个内存流或许是更好的做法,这次算你赢了 Copilot,但在我给 CsvHelper 提交的最初的拉取请求中,我并没有这么做,不过应该也没什么问题。

public class BenchmarkWriteCsv 
{ 
    private const int entryCount = 10000; 
    private readonly List records = new(entryCount); 

    public class Simple 
    { 
        public int Id1 { get; set; } 
        public int Id2 { get; set; } 
        public string Name1 { get; set; } 
        public string Name2 { get; set; } 
    } 

    [GlobalSetup] 
    public void GlobalSetup() 
    { 
        var random = new Random(42); 
        var chars = new char[10]; 

        string getRandomString() 
        { 
            for (int i = 0; i < 10; ++i) 
                chars[i] = (char)random.Next('a', 'z' + 1); 
            return new string(chars); 
        } 

        for (int i = 0; i < entryCount; ++i) 
        { 
            records.Add(new Simple 
            { 
                Id1 = random.Next(), 
                Id2 = random.Next(), 
                Name1 = getRandomString(), 
                Name2 = getRandomString(), 
            }); 
        } 
    } 

    [Benchmark] 
    public void WriteRecords() 
    { 
        using var stream = new MemoryStream(); 
        using var streamWriter = new StreamWriter(stream); 
        using var writer = new CsvHelper.CsvWriter(streamWriter, CultureInfo.InvariantCulture); 
        writer.WriteRecords(records); 
        streamWriter.Flush(); 
    } 
} 

深入了解基准测试

  现在开始分析,我既可以让 Profiler Agent 运行基准测试,也可以直接点击后续提示“@Profiler Run the benchmark and analyze results”。从这里开始,Copilot 会编辑我的主方法,乍一看可能有些奇怪,但查看所做的更改后,我发现它为了使用 BenchmarkSwitcher 进行了必要的修改,这样就能选择要运行的基准测试了:

static void Main(string[] args)
{
    // Use assembly-wide discovery so all benchmarks in this assembly are run,
    // including the newly added BenchmarkWriteRecords.
    _ = BenchmarkSwitcher.FromAssembly(typeof(BenchmarkEnumerateRecords).Assembly).Run(args);
}

  然后它启动了一次基准测试运行,完成后会给我一个诊断会话,我可以在其中开始调查。

使用 Copilot Profiler Agent 来查找瓶颈

  现在到了令人兴奋的部分。运行基准测试后,Profiler Agent 会分析跟踪信息,并突出显示时间的消耗位置。我可以向 Profiler Agent 询问有关跟踪的问题,让它解释代码为什么运行缓慢,或者某些优化为何会有帮助。它已经指出,大部分时间都花在委托编译和调用上,这是针对 CSV 记录中的每个字段进行的。对于一个有 4 个字段、被写入 10,000 次的记录来说,这意味着会有 40,000 次委托调用。每次调用都有开销,而这在分析器中显示为一个热点路径。

6

  我可以问 Profiler Agent:“我怎样才能减少委托调用的开销?”或者“为什么委托调用很慢?”,而它会像一位耐心的老师一样解释相关概念并提出修复建议。

实施修复方案

  我点击 @Profiler Optimize library to produce a single compiled write delegate (reduce multicast invokes),看看会得到什么结果。 Profiler Agent 会对 ObjectRecordWriter 进行编辑,我可以在聊天窗口中点击它来查看所做更改的差异。

  查看当前的实现,代码构建了一个委托列表,每个字段对应一个委托:

var delegates = new List<Action>();

foreach (var memberMap in members)
{
    // ... field writing logic ...

    delegates.Add(Expression.Lambda<Action>(writeFieldMethodCall, recordParameter).Compile());
}

var action = CombineDelegates(delegates) ?? new Action((T parameter) => { });
return action;

  问题在于 CombineDelegates 会创建一个多播委托,该委托会依次单独调用每个独立的委托。相反,Profiler Agent 建议我们在编译前使用 Expression.Block 来组合所有表达式:

var expressions = new List<Expression>(members.Count);

foreach (var memberMap in members)
{
    // ... field writing logic ...

    expressions.Add(writeFieldMethodCall);
}

if (expressions.Count == 0)
{
    return new Action<T>((T parameter) => { });
}

// Combine all field writes into a single block
var block = Expression.Block(expressions);
return Expression.Lambda<Action<T>>(block, recordParameter).Compile();

  这一改动虽小却很精妙:我们没有创建多个委托并按顺序调用它们,而是创建了一个包含所有字段写入操作的单个块表达式,然后对其进行一次编译。现在,当我们为每条记录调用委托时,所有字段都会在一次调用中完成写入,不存在额外的委托开销。

衡量影响

  做出这一更改后,Copilot 会自动重新运行基准测试以衡量改进效果。结果显示,在此次使用分析器的运行中,性能大约提升了 24%。我们之前为 CsvHelper 准备的分阶段拉取请求显示性能提升了约 15%。CPU 分析器证实,我们已经消除了委托调用的开销,对于每条有 4 个字段的 10,000 条记录,之前需要进行 40,000 次委托调用,而现在只需要 10,000 次委托调用。

9

  对于一个已经经过大量优化的库来说,这是一场意义重大的胜利。对于那些编写包含许多字段的大型 CSV 文件的应用程序而言,这一改进直接意味着 CPU 时间的减少和处理速度的提升。而且,由于 CsvHelper 的下载量高达数百万次,这项优化惠及了大量用户。在此基础上,我继续推进并提交了拉取请求,不过 Copilot 贴心地提供了更多关于类型转换和 ShouldQuote 逻辑的后续提示,以便我能进一步提升性能。

Copilot Profiler Agent 的价值

  这个工作流程之所以强大,是因为它将 Visual Studio Profiler 提供的精确性能数据与 Copilot 的分析和代码生成能力相结合。您无需手动深入研究 CPU 跟踪并试图理解热点路径的含义,而是可以提出自然语言问题,获取可执行的见解,并快速测试想法。

  该 Agent 不仅会告诉您哪些部分运行缓慢,还会帮助您理解其缓慢的原因,并提出具体的修复方法。在这种情况下,它识别出委托调用的开销是瓶颈,并建议采用 Expression.Block 优化,这正是解决该问题的正确方案。它甚至还重新运行了基准测试来确认该优化的效果!

让我们知道您的想法

  我们已经展示了 Copilot Profiler Agent 如何帮助您处理实际项目,通过自然语言查询识别性能瓶颈,并在数据支持下做出有意义的改进。当您能够就性能数据提出问题并获得智能答案时,测量/更改/测量的循环会变得快得多。我们很想听听您的想法!

原文链接:https://devblogs.microsoft.com/visualstudio/delegate-the-analysis-not-the-performance/

me