My C#
WinForms
program runs on a Windows 7
client machine and submits SELECT
queries to a SQL Server
instance on a remote server (see DB code snippet below). I think I'm correct in categorizing the code that processes the query results (a series of of DataTables
) as CPU bound
, but I'm not confident in how to categorize my DB code (see below) that runs on the client machine. On one hand, its associated with I/O, but I'm thinking that all the I/O resources used are on the remote DB server and handled by the SQL Server instance and not the Win 7 client machine and so even my DB code is CPU-bound
.
Should I treat/program my DB code that runs on the client machine as CPU bound
or I/O bound
? Or, does using TPL Dataflow
make this point moot?
My DB Code
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();
}
}
Should I treat/program my DB code that runs on the client machine as CPU bound or I/O bound
I think the rule of thumb here is if its not in a loop and doing calculations, its probably IO bound. Anything that access a network resource, filesystem or waits for a device to respond is probably IO
More over, not everything in a program consumes CPU time. When a thread tries to read data from a file on disk or sends a TCP/IP packet through network, the only thing it does is delegate the actual work to a device, disk or network adapter, and waits for results.
It’s very expensive to spend a threads’ time on waiting. Even through threads sleep and don’t consume CPU time while waiting for the results, it doesn’t really pay off because it’s a waste of system resources.
Is your request IO? DB's get a little murky however the answer is yes.
TPL Dataflow or not, you just don't want to create threads or use resources waiting for IO bound tasks to complete
So the async/await pattern works well or you can use TPL Dataflow block as well. The premise is you don't create huge amounts of tasks that sit there waiting. With ActionBlock
you can configure the max amount of tasks and reuse them for all the items that meanwhile sit in a buffer waiting for a task.
Example
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;