【问题标题】:Very slow ToListAsync() compared to ToList()与 ToList() 相比, ToListAsync() 非常慢
【发布时间】:2015-11-10 12:45:28
【问题描述】:

我有一个包含分组和多个包含的复杂 LINQ 查询。我发现 ToListAsync() 需要超过一秒才能完成,而 ToList() 会在几分之一秒内返回。

allReservationsList = allReservations.ToList(); // fast
allReservationsList = await allReservations.ToListAsync(); // more then a second for 60 rows

我做错了什么还是实体框架有问题?

这里是查询:

            var reservations = db.Reservations
                .Include(r => r.PickUpLocation)
                .Include(r => r.ReturnLocation)
                .Include(r => r.RequestedVehicleModel).ThenInclude(m => m.Photos)
                .Include(r => r.RequestedVehicleModel.VehicleType.VehicleModels)
                .Include(r => r.RequestedVehicleType).ThenInclude(t => t.Photos)
                .Include(r => r.AssignedUnit.VehicleModel.VehicleType)
                .Include(r => r.DailyPrice.Currency);

            var allReservations =
                from r in reservations
                orderby r.VersionDate descending
                group r by r.BookingCode into g
                select g;

【问题讨论】:

  • 能否提供您的查询和相关代码?我唯一能说的就是克里斯在下面说的话。由于开销,一个操作的异步总是比同步调用慢。
  • @MaximeRouiller 我添加了查询。性能差异太大,无法用开销来解释,可能是 100 倍。
  • 这几乎可以肯定是因为 Photos 表包含 varbinary(max) 和/或 [n]varchar(max) 列。 stackoverflow.com/questions/28543293/…

标签: asp.net-core-mvc entity-framework-core


【解决方案1】:

这里的变量太多了。但是,一般来说,异步方法的返回时间会比同步方法长,这仅仅是因为异步的开销更大。这是否会导致您看到的整个延迟,至少根据您提供的信息无法判断。

【讨论】:

  • 我添加了查询。我会理解 50%,甚至 100% 的差异。但我看到的可能是100s的时差。 ToList() 几乎立即完成,而 ToListAsync() 需要一秒钟以上。在 VS 诊断工具中,我可以在 CPU 利用率图表上非常清楚地看到它 - 一个小而短的峰值与超过一秒钟的高负载。
  • 再一次,有太多变数无法说明发生了什么。不过,这对我来说似乎是过早的优化。发布到您的生产环境的代理,加载并在那里对其进行分析。如果此时有问题,那么您可以继续尝试优化。至少那时您将有更多相关数据可供使用。就目前而言,我想说别担心。
  • 这正是我开始研究问题的原因:生产环境中的响应时间太慢。所以我弄清楚是什么函数调用使它变慢,用同步模拟替换它,它解决了性能问题。它像这样工作得很好,但对我来说异步调用比同步调用慢数百倍似乎很奇怪。
  • 除了固有的开销之外,唯一可以真正使异步花费更长的时间是如果没有可用的线程。就像同步操作一样,如果所有线程都被占用,你就会排队,一旦异步操作需要继续处理,在放弃它的线程后,它必须等到一个线程可用,如果有线程就会排队没有。但是,如果发生这种情况,则说明您的服务器负载过大,您需要为其提供更多资源。
  • 即使在一个请求的测试环境中,我也能看到这一点。此外,CPU 利用率图表显示 CPU 负载高超过一秒,因此它实际上是在做一些 CPU 密集型的事情。
【解决方案2】:

如this SO answer 中所述,如果您使用大型列类型(blob、varchar(max) 等),则使用 ToListAsync() 时,Entity Framework 6 will perform poorly。我不能说我 100% 理解造成这种情况的复杂性,但只要说如果您要检索这样的大数据值,使用 ToList() 是正确的就足够了。

【讨论】:

  • 我把它改成了 ToList() 调用速度更快了!
猜你喜欢
  • 2016-07-18
  • 2021-02-13
  • 2017-05-07
  • 2014-12-31
  • 1970-01-01
  • 2015-01-27
  • 2014-09-06
  • 1970-01-01
  • 2019-07-26
相关资源
最近更新 更多