C#async /等待读取DbDataReader时的效率(或滥用)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#async /等待读取DbDataReader时的效率(或滥用),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4434字,纯文字阅读大概需要7分钟。
内容图文
偶然发现了一段相对经常使用的代码,这些代码起初似乎效率低下. (我知道有时优化可能是邪恶的,但我在想)
介绍部分 – 读取返回数据的相当简单的SP执行:
try
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandText = sql.ToString();
command.Parameters.AddRange(sqlParameters.ToArray());
var reader = await command.ExecuteReaderAsync();
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
var item = await GetProjectElement(reader);
list.Add(item);
}
}
reader.Dispose();
}
}
finally
{
connection.Close();
}
让我担心的是功能
await GetProjectElement(reader)
private async Task<Project> GetProjectElement(DbDataReader reader)
{
var item = new Project
{
Id = await reader.GetFieldValueAsync<int>(1),
ParentId = await reader.IsDBNullAsync(2) ? default(int?) : await reader.GetFieldValueAsync<int>(2),
Name = await reader.IsDBNullAsync(3) ? default(string) : await reader.GetFieldValueAsync<string>(3),
Description = await reader.IsDBNullAsync(4) ? default(string) : await reader.GetFieldValueAsync<string>(4),
Address = await reader.IsDBNullAsync(5) ? default(string) : await reader.GetFieldValueAsync<string>(5),
City = await reader.IsDBNullAsync(6) ? default(string) : await reader.GetFieldValueAsync<string>(6),
PostalCode = await reader.IsDBNullAsync(7) ? default(string) : await reader.GetFieldValueAsync<string>(7),
Type = (ProjectTypeEnum)(await reader.GetFieldValueAsync<byte>(8)),
StartDate = await reader.IsDBNullAsync(9) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(9),
EstimatedEndDate = await reader.IsDBNullAsync(10) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(10),
ActualEndDate = await reader.IsDBNullAsync(11) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(11),
WebsiteUrl = await reader.IsDBNullAsync(12) ? default(string) : await reader.GetFieldValueAsync<string>(12),
Email = await reader.IsDBNullAsync(13) ? default(string) : await reader.GetFieldValueAsync<string>(13),
PhoneNumber = await reader.IsDBNullAsync(14) ? default(string) : await reader.GetFieldValueAsync<string>(14),
MobilePhoneNumber = await reader.IsDBNullAsync(15) ? default(string) : await reader.GetFieldValueAsync<string>(15),
Key = await reader.IsDBNullAsync(16) ? default(Guid?) : await reader.GetFieldValueAsync<Guid>(16),
OrganizationElementId = await reader.GetFieldValueAsync<int>(17),
CompanyOrganizationElementId = await reader.IsDBNullAsync(18) ? default(int?) : await reader.GetFieldValueAsync<int>(18),
IsArchived = await reader.GetFieldValueAsync<bool>(20),
IsDeleted = await reader.GetFieldValueAsync<bool>(21),
CreatedOn = await reader.GetFieldValueAsync<DateTime>(22),
CreatedBy = await reader.GetFieldValueAsync<string>(23),
ModifiedOn = await reader.IsDBNullAsync(24) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(24),
ModifiedBy = await reader.IsDBNullAsync(25) ? default(string) : await reader.GetFieldValueAsync<string>(25)
};
return item;
}
正如你所看到的那样,有很多await调用,编译器变成了状态机,不是吗?
您可以找到编译器生成的代码看起来像here的简化版本.
大量的GOTO意味着一遍又一遍地进行上下文切换.
由于SP在未指定CommandBehavior的情况下执行 – 数据将处于非顺序模式. (可能原因是对于Project link的这种情况,表行不应该是非常大的字节数)
我的问题是:
1)这是滥用async / await没有明显原因,因为行数据已经缓存在内存中,对吗?
2)是Task< Project>这种情况下的纯粹开销?
3)与没有等待的方法相比,这种方法实际上会有更差的表现
最后的结果:如果我把事情做对了,我们会想要对大表行使用CommandBehavior.SequentialAccess,其内容可能会超过合理的长度,从而使我们想要异步读取它? (比如存储varbinary(max)或blob)
解决方法:
正如其他人所指出的那样,GOTO不会导致上下文切换,而且速度非常快.
1) is this abusing of the async/await without an obvious reason, because the row data is already buffered in memory, right?
ADO.NET允许实现者在如何实现基类型方面有很大的余地.也许这行是在记忆中,也许不是.
2) is Task a pure overhead in this scenario?
是的,如果操作实际上是同步的.这是ADO.NET提供程序的实现细节.
请注意,状态机和await在这里几乎没有增加开销;有一个async fast path,代码只是在可能的情况下保持同步执行.
3) would this approach actually have a worse performance compared to one without awaiting
可能不是.首先,性能影响不会由调用每个方法并继续同步执行的少量CPU工作来驱动.您看到的任何性能影响都归因于额外的任务< T>在Gen0堆上抛出的实例,必须进行垃圾回收.这就是现在有一个ValueTask< T>的原因.
但即使是性能影响也很可能在网络I / O调用数据库服务器之后无法察觉.也就是说,如果你想知道微观性能的惩罚,Zen of Async就是经典之作.
内容总结
以上是互联网集市为您收集整理的C#async /等待读取DbDataReader时的效率(或滥用)全部内容,希望文章能够帮你解决C#async /等待读取DbDataReader时的效率(或滥用)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。