C# 实体框架6异步方法与同步方法的性能
我修改了一个Github项目,以测试一些与实体框架相关的查询方式 型号:C# 实体框架6异步方法与同步方法的性能,c#,entity-framework,asynchronous,C#,Entity Framework,Asynchronous,我修改了一个Github项目,以测试一些与实体框架相关的查询方式 型号: [Table("Player")] public partial class Player { public int Id { get; set; } [Required] [StringLength(200)] public string FirstName { get; set; } [Required] [StringLength(200)] public
[Table("Player")]
public partial class Player
{
public int Id { get; set; }
[Required]
[StringLength(200)]
public string FirstName { get; set; }
[Required]
[StringLength(200)]
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public int TeamId { get; set; }
public virtual Team Team { get; set; }
}
[Table("Team")]
public partial class Team
{
public Team()
{
Players = new HashSet<Player>();
}
public int Id { get; set; }
[Required]
[StringLength(200)]
public string Name { get; set; }
public DateTime FoundingDate { get; set; }
public int SportId { get; set; }
public virtual ICollection<Player> Players { get; set; }
public virtual Sport Sport { get; set; }
}
[Table("Sport")]
public partial class Sport
{
public Sport()
{
Teams = new HashSet<Team>();
}
public int Id { get; set; }
[StringLength(100)]
public string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
EF“Async”-FirstOrDefaultAsync()和ToListAsync()
EF与Select into DTO对象“同步”
context.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).FirstOrDefault(x => x.Id == id);
context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList();
context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO()
{
Id = t.Id,
FoundingDate = t.FoundingDate,
Name = t.Name,
SportId = t.SportId,
Players = t.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList()
}).ToList();
await context.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).FirstOrDefaultAsync(x => x.Id == id);
await context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToListAsync();
await context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO()
{
Id = t.Id,
FoundingDate = t.FoundingDate,
Name = t.Name,
SportId = t.SportId,
Players = t.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList()
}).ToListAsync();
EF“异步”与Select into DTO对象
context.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).FirstOrDefault(x => x.Id == id);
context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList();
context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO()
{
Id = t.Id,
FoundingDate = t.FoundingDate,
Name = t.Name,
SportId = t.SportId,
Players = t.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList()
}).ToList();
await context.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).FirstOrDefaultAsync(x => x.Id == id);
await context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToListAsync();
await context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO()
{
Id = t.Id,
FoundingDate = t.FoundingDate,
Name = t.Name,
SportId = t.SportId,
Players = t.Players.Select(p => new PlayerDTO()
{
Id = p.Id,
FirstName = p.FirstName,
DateOfBirth = p.DateOfBirth,
LastName = p.LastName,
TeamId = p.TeamId
}).ToList()
}).ToListAsync();
我想我的结果很麻烦。主要是因为MS正在大量提升EF的异步部分
我的结果:(以毫秒为单位)
运动项目数量:8个,团队数量:30个,运动员数量:100个
EntityFrameworkAsyncDTO Results
Run # Player by ID Players per Team Teams per Sport
0 1,46 3,47 35,88
1 1,04 3 33
2 1,02 3,3 33,75
3 1,03 3 31,75
4 1,1 3,27 31,38
EntityFrameworkAsync Results
Run # Player by ID Players per Team Teams per Sport
0 1,17 3,53 57
1 1,01 3 48,62
2 0,99 3,03 47,88
3 1,02 3,07 51
4 1 3,03 48,88
EntityFrameworkDTO Results
Run # Player by ID Players per Team Teams per Sport
0 0,02 3 13,25
1 0,01 2,8 13,12
2 0,15 2,97 13,25
3 0,02 2,9 13,25
4 0,05 2,8 13,12
EntityFramework Results
Run # Player by ID Players per Team Teams per Sport
0 0,01 2,27 28,38
1 0,01 2,4 28,25
2 0 2,13 28,5
3 0,01 2,17 27,5
4 0,01 2,13 29
ADONET Results
Run # Player by ID Players per Team Teams per Sport
0 0 2,03 11,75
1 0 2 12,62
2 0 2 11,38
3 0 2 12,38
4 0 2 11,25
/编辑我已将ADO.NET时间添加到结果列表中作为参考
我的问题是:由于加载时间如此不同,我的查询是否做错了什么
在我运行的真实系统中,我将所有的异步DB调用更改为同步调用,从统计数据中可以看出,系统的DB调用速度提高了约50%。这是一个有100-120个当前用户通过信号机连接的系统,它的分贝很重。我想详细解释一下
Async速度不快,在普通的“sync”代码的基础上增加了很多开销。但它允许在浪费等待时间的情况下更好地使用资源(例如网络连接的高延迟等)异步方法意味着更多的IL代码,从而解释了一次性调用的这些差异 如果在方法中进行其他异步调用,则可以获得异步方法的好处
另一篇有趣的文章:如果您按如下方式运行异步测试,我同意其他贡献者的观点:
var tskPlayers = context.Players.FirstOrDefaultAsync(x => x.Id == id);
var tskPlayersNt = context.Players.AsNoTracking().Where(x => x.TeamId == teamId).ToListAsync();
var tskTeamsNt = context.Teams.AsNoTracking().Include(x => x.Players).Where(x => x.SportId == sportId).ToListAsync();
Task.WhenAll(tskPlayers, tskPlayersNt, tskTeamsNt);
您将看到更好的结果。您希望比较First与FirstAsync,并查找与FindAsync的比较。首先,你会发现你做了很多不同的工作。而且,
Async
并不是“更快”。这会增加很多开销。但它允许在等待网络通信时使用时间。我知道Async/Await有开销,但我不认为通过EF进行的SQL调用会慢2-4倍。我知道Find与First不同。我已经将代码改为使用First而不是FindAsync,在使用大型列(如varbinary(MAX)、varchar(MAX)、nvarchar(MAX)或XML)时,这种情况也会变得更糟。请参阅:测试会多次运行。