使用 async/await + TPL 数据流在远程服务器上执行 SQL select 语句:CPU 或 I/O 绑定?
Executing SQL select statements on a remote server using async/await + TPL dataflow: CPU or I/O bound?
我的 C#
WinForms
程序在 Windows 7
客户端计算机上运行,并向远程服务器上的 SQL Server
实例提交 SELECT
查询(请参阅数据库下面的代码片段)。我认为我将处理查询结果(一系列 DataTables
)的代码归类为 CPU bound
是正确的,但我对如何归类我的数据库代码没有信心(见下文)在客户端机器上运行。一方面,它与 I/O 相关联,但我认为所有使用的 I/O 资源都在远程数据库服务器上并由 SQL 服务器实例处理,而不是 Win 7客户端机器,所以即使我的数据库代码也是 CPU-bound
.
我应该 treat/program 我在客户端计算机上运行的数据库代码是 CPU bound
还是 I/O bound
?或者,使用 TPL Dataflow
会使这一点变得毫无意义吗?
我的数据库代码
using (SqlConnection sqlConnection = new SqlConnection("Data Source=" + MachineName + ReplaceInstanceName + "; Initial Catalog=" + DbName + "; Integrated Security=True;Connection Timeout=10"))
{
using (SqlCommand sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.Parameters.AddWithValue("@SearchString", "%" + userProvidedSearchString + "%");
sqlCommand.CommandText = queryString;
sqlConnection.Open();
SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync(ct);
dataTable_TableDataFromFieldQuery.Load(sqlDataReader);
sqlConnection.Close();
}
}
数据存储在数据库服务器的磁盘上,因此大部分 IO 将在那里发生,数据库引擎在这里查询并 returns 将数据发送给调用者(您的应用程序)。连接的两端都会有 CPU 和内存使用,直到您从 SQL 服务器检索到所有批次的数据,此时您将对应用程序内存中的这些行进行操作.
所以你的机器没有受到 IO 攻击;这发生在数据所在的地方。但是,您的代码导致 IO 发生在数据库服务器上,因此请根据您的意愿进行解释。
Should I treat/program my DB code that runs on the client machine as
CPU bound or I/O bound
我认为这里的经验法则是,如果它不在循环中并进行计算,则它可能受 IO 限制。任何访问网络资源、文件系统或等待设备响应的东西都可能是 IO
此外,并非程序中的所有内容都会消耗 CPU 时间。当线程试图从磁盘上的文件读取数据或通过网络发送 TCP/IP 数据包时,它所做的唯一一件事就是将实际工作委托给设备、磁盘或网络适配器,并等待结果。
将一个线程的时间花在等待上是非常昂贵的。即使通过线程休眠并且在等待结果时不消耗 CPU 时间,它也不会真正得到回报,因为它是对系统资源的浪费。
你的请求是IO吗? DB 有点模糊,但答案是肯定的。
TPL Dataflow 与否,您只是不想创建线程或使用等待 IO 绑定任务完成的资源
因此 async/await 模式效果很好,或者您也可以使用 TPL 数据流块。前提是您不会创建大量等待的任务。使用 ActionBlock
,您可以配置最大任务数量,并将它们重复用于同时位于缓冲区中等待任务的所有项目。
例子
var block = new ActionBlock<MySomething>(
mySomething => MyMethodAsync(mySomething),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });
foreach (var something in ListOfSomethings)
{
block.Post(something );
}
block.Complete();
await block.Completion;
我的 C#
WinForms
程序在 Windows 7
客户端计算机上运行,并向远程服务器上的 SQL Server
实例提交 SELECT
查询(请参阅数据库下面的代码片段)。我认为我将处理查询结果(一系列 DataTables
)的代码归类为 CPU bound
是正确的,但我对如何归类我的数据库代码没有信心(见下文)在客户端机器上运行。一方面,它与 I/O 相关联,但我认为所有使用的 I/O 资源都在远程数据库服务器上并由 SQL 服务器实例处理,而不是 Win 7客户端机器,所以即使我的数据库代码也是 CPU-bound
.
我应该 treat/program 我在客户端计算机上运行的数据库代码是 CPU bound
还是 I/O bound
?或者,使用 TPL Dataflow
会使这一点变得毫无意义吗?
我的数据库代码
using (SqlConnection sqlConnection = new SqlConnection("Data Source=" + MachineName + ReplaceInstanceName + "; Initial Catalog=" + DbName + "; Integrated Security=True;Connection Timeout=10"))
{
using (SqlCommand sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.Parameters.AddWithValue("@SearchString", "%" + userProvidedSearchString + "%");
sqlCommand.CommandText = queryString;
sqlConnection.Open();
SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync(ct);
dataTable_TableDataFromFieldQuery.Load(sqlDataReader);
sqlConnection.Close();
}
}
数据存储在数据库服务器的磁盘上,因此大部分 IO 将在那里发生,数据库引擎在这里查询并 returns 将数据发送给调用者(您的应用程序)。连接的两端都会有 CPU 和内存使用,直到您从 SQL 服务器检索到所有批次的数据,此时您将对应用程序内存中的这些行进行操作.
所以你的机器没有受到 IO 攻击;这发生在数据所在的地方。但是,您的代码导致 IO 发生在数据库服务器上,因此请根据您的意愿进行解释。
Should I treat/program my DB code that runs on the client machine as CPU bound or I/O bound
我认为这里的经验法则是,如果它不在循环中并进行计算,则它可能受 IO 限制。任何访问网络资源、文件系统或等待设备响应的东西都可能是 IO
此外,并非程序中的所有内容都会消耗 CPU 时间。当线程试图从磁盘上的文件读取数据或通过网络发送 TCP/IP 数据包时,它所做的唯一一件事就是将实际工作委托给设备、磁盘或网络适配器,并等待结果。
将一个线程的时间花在等待上是非常昂贵的。即使通过线程休眠并且在等待结果时不消耗 CPU 时间,它也不会真正得到回报,因为它是对系统资源的浪费。
你的请求是IO吗? DB 有点模糊,但答案是肯定的。
TPL Dataflow 与否,您只是不想创建线程或使用等待 IO 绑定任务完成的资源
因此 async/await 模式效果很好,或者您也可以使用 TPL 数据流块。前提是您不会创建大量等待的任务。使用 ActionBlock
,您可以配置最大任务数量,并将它们重复用于同时位于缓冲区中等待任务的所有项目。
例子
var block = new ActionBlock<MySomething>(
mySomething => MyMethodAsync(mySomething),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });
foreach (var something in ListOfSomethings)
{
block.Post(something );
}
block.Complete();
await block.Completion;