DbSet<TEntity>.Local.Any() 将 EF Core 从 2.2.6 升级到 3.1.3 时出现性能问题
DbSet<TEntity>.Local.Any() performance issue when upgraging EF Core from 2.2.6 to 3.1.3
有一种方法负责根据我们的 git 提交缓存数据库 table 中的哈希返回单个 GitCommit 对象。我们使用 Entity Framework Core,当我 将 nuget 包从 2.2.6 升级到 3.1.3 时,我意识到一个奇怪的性能问题。从第二次调用 2.2.6 的方法开始,条件 _dbContext.GitCommitCache.Local.Any() 在 3.1 上执行了 0-1ms .3 通常需要 150-220ms。我 运行 这个方法大约 9 到 1 万次,这是一个巨大的性能瓶颈。是否有任何相关的内容在幕后发生了变化?这是否有任何简单的解决方案来保持原始性能?
public async Task<GitCommit> GetCommitAsync(string hash)
{
try
{
await _semaphore.WaitAsync();
if (!_dbContext.GitCommitCache.Local.Any())
{
await _dbContext.GitCommitCache.LoadAsync();
}
var cacheEntry = await _dbContext.GitCommitCache.FindAsync(hash);
if (cacheEntry != null)
{
return cacheEntry;
}
var commit = await GetCommitDataAsync(hash);
try
{
_dbContext.GitCommitCache.Add(commit);
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateException)
{
_dbContext.Entry(commit).State = EntityState.Detached;
}
return commit;
}
finally
{
_semaphore.Release();
}
}
在issue #14001中,即EF core 3.0.0,新增访问Local
时调用DetectChanges
:
public override LocalView<TEntity> Local
{
get
{
CheckKey();
if (_context.ChangeTracker.AutoDetectChangesEnabled)
{
_context.ChangeTracker.DetectChanges();
}
return _localView ??= new LocalView<TEntity>(this);
}
}
DetectChanges
是一种复杂的方法,因此相对较慢。幸运的是,如您所见,如果您暂时禁用 AutoDetectChangesEnabled
,只是为了调用 Local
,您将再次加快速度。
我认为这样做是安全的,前提是当您输入该方法时 _dbContext
中没有未检测到的更改。
有一种方法负责根据我们的 git 提交缓存数据库 table 中的哈希返回单个 GitCommit 对象。我们使用 Entity Framework Core,当我 将 nuget 包从 2.2.6 升级到 3.1.3 时,我意识到一个奇怪的性能问题。从第二次调用 2.2.6 的方法开始,条件 _dbContext.GitCommitCache.Local.Any() 在 3.1 上执行了 0-1ms .3 通常需要 150-220ms。我 运行 这个方法大约 9 到 1 万次,这是一个巨大的性能瓶颈。是否有任何相关的内容在幕后发生了变化?这是否有任何简单的解决方案来保持原始性能?
public async Task<GitCommit> GetCommitAsync(string hash)
{
try
{
await _semaphore.WaitAsync();
if (!_dbContext.GitCommitCache.Local.Any())
{
await _dbContext.GitCommitCache.LoadAsync();
}
var cacheEntry = await _dbContext.GitCommitCache.FindAsync(hash);
if (cacheEntry != null)
{
return cacheEntry;
}
var commit = await GetCommitDataAsync(hash);
try
{
_dbContext.GitCommitCache.Add(commit);
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateException)
{
_dbContext.Entry(commit).State = EntityState.Detached;
}
return commit;
}
finally
{
_semaphore.Release();
}
}
在issue #14001中,即EF core 3.0.0,新增访问Local
时调用DetectChanges
:
public override LocalView<TEntity> Local
{
get
{
CheckKey();
if (_context.ChangeTracker.AutoDetectChangesEnabled)
{
_context.ChangeTracker.DetectChanges();
}
return _localView ??= new LocalView<TEntity>(this);
}
}
DetectChanges
是一种复杂的方法,因此相对较慢。幸运的是,如您所见,如果您暂时禁用 AutoDetectChangesEnabled
,只是为了调用 Local
,您将再次加快速度。
我认为这样做是安全的,前提是当您输入该方法时 _dbContext
中没有未检测到的更改。