You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

附加Visual Studio调试器时await/async操作性能骤降问题求助

VS2022调试EF Core异步查询性能暴跌的问题排查与解决建议

问题现象

全新安装Visual Studio 2022社区版后,排查EF Core导入器性能问题时发现:

  • 使用FirstOrDefaultAsync异步查询时,附加调试器运行每个搜索线程耗时17-18秒,但不附加调试器时耗时不足1秒。
  • 改用同步方法FirstOrDefault后,无论是否附加调试器,线程耗时均小于1秒。
  • 已尝试禁用“调试时启用诊断工具”,无明显改善。

复现测试代码

public class TestItem
{
    [Key]
    public Guid Id { get; set; }
    public int TestNum { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<TestItem> TestItems { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseNpgsql("Host=localhost;Database=efdebugtest;Username=postgres;Password=...");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<TestItem>().HasIndex(r => r.TestNum);
    }
}

internal class Program
{
    static async Task Main(string[] args)
    {
        void L(string str) => Console.WriteLine(str);

        using var ctx = new AppDbContext();
        await ctx.Database.EnsureDeletedAsync();
        await ctx.Database.MigrateAsync();
        var sw = new Stopwatch();
        sw.Start();
        var items = Enumerable.Range(0, 100_000).Select(i => new TestItem()
        {
            Id = Guid.NewGuid(),
            TestNum = i,
        });
        L($"Items Generated: {sw.Elapsed.TotalSeconds}s");

        sw.Restart();
        await ctx.AddRangeAsync(items);
        L($"Items Added: {sw.Elapsed.TotalSeconds}s");

        sw.Restart();
        await ctx.SaveChangesAsync();
        L($"Items Saved: {sw.Elapsed.TotalSeconds}s");

        ConcurrentBag<int> foundItems = new();
        var testChunks = Enumerable.Range(0, 200_000).OrderBy(_ => Guid.NewGuid()).Take(20_000).Chunk(2500);
        await Parallel.ForEachAsync(testChunks, async (chunk, cancellationToken) =>
        {
            using var threadCtx = new AppDbContext();
            var threadSw = new Stopwatch();
            threadSw.Start();
            foreach (var num in chunk)
            {
                var dbEntry = await threadCtx.TestItems.FirstOrDefaultAsync(ti => ti.TestNum == num);
                if (dbEntry != null)
                {
                    foundItems.Add(dbEntry.TestNum);
                }
            }
            L($"Thread finished search: {threadSw.Elapsed.TotalSeconds}s");
        });
    }
}

性能对比

  • 附加调试器输出:
Items Generated: 0.0003297s
Items Added: 0.6718225s
Items Saved: 4.2752014s
Thread finished search: 17.2668618s
Thread finished search: 17.2820979s
...
Thread finished search: 17.4786316s
Thread finished search: 17.4891402s
  • 不附加调试器输出:
Items Generated: 0.0002435s
Items Added: 0.6201017s
Items Saved: 4.025146s
Thread finished search: 0.8171215s
Thread finished search: 0.8336687s
...
Thread finished search: 0.8410876s
Thread finished search: 0.8419168s

调试器设置调整方案

以下是针对VS2022调试器的设置调整,可解决异步查询性能暴跌问题:

  • 禁用“仅我的代码”
    路径:工具 -> 选项 -> 调试 -> 常规,取消勾选「启用仅我的代码」。
    调试器跟踪异步代码时,该功能会额外加载符号并跳过非用户代码,导致异步调度开销剧增。

  • 关闭“异步调试”
    路径:工具 -> 选项 -> 调试 -> 常规,取消勾选「启用异步调试」。
    此设置会牺牲异步调用链的追踪能力,但能大幅降低异步调试的性能开销,适合仅需调试业务逻辑的场景。

  • 调整符号加载策略
    路径:工具 -> 选项 -> 调试 -> 符号,选择「仅指定模块加载符号」,或取消勾选「Microsoft符号服务器」。
    调试器加载大量系统/第三方库符号(如EF Core、Npgsql的异步相关符号)会增加CPU和IO开销,多线程异步场景下尤为明显。

  • 禁用“托管兼容模式”
    路径:工具 -> 选项 -> 调试 -> 常规,取消勾选「使用托管兼容模式」。
    该模式为兼容旧.NET框架设计,在.NET 6+异步场景下可能造成不必要的性能损耗。

  • 关闭调试时热重载
    路径:工具 -> 选项 -> 调试 -> 热重载,取消勾选「调试时启用热重载」(若已开启)。
    热重载在调试异步代码时可能注入额外检测逻辑,影响性能。

补充说明

  • 上述设置可按需切换,部分设置会牺牲少量调试功能,但能让异步调试性能接近无调试器状态。
  • 若需保留完整调试功能,建议将VS2022升级到最新版本,微软后续更新中修复过部分异步调试的性能问题。

内容的提问来源于stack exchange,提问作者Zak123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:46:07