ASYNC_NETWORK_IO for dummies

Leave a comment

I often come across “less than optimal” applications, when I do performance tuning. You know, that kind of application that are kind of responsive, but the main issue is the slowness. Everything about the application is sloooow…

What is one of the signs that you might have a slow client application? (Disclaimer: Slow = Doesn’t consume SQL Server data in zero or less milliseconds. All applications are more or less slow, but abnormal slowness can make users mad.)

The magical query:

FROM sys.dm_os_wait_stats
order by wait_time_ms desc

According to Guy Bowermans article, the statistics lifetime is (about) the time of the SQLTRACE_INCREMENTAL_FLUSH_SLEEP.

I now did some illustrative tests: I wrote an extremely simple console application, selecting the ID column from a table with ~1000000 rows.

Code: (C#, Console project)

static void Main(string[] args)

SqlConnection con = new SqlConnection(“Data Source=.;Initial Catalog=testdata;Integrated Security=SSPI;”);
SqlCommand cmd = new SqlCommand(“SELECT SalesOrderID FROM [Sales].[SalesOrderDetail]”, con);
SqlCommand cmdclearstat = new SqlCommand(“DBCC SQLPERF (‘sys.dm_os_wait_stats’, CLEAR);”, con);


SqlDataReader rdr = cmd.ExecuteReader();

while (rdr.Read())
int a = rdr.GetInt32(0);



When I ran this code, the SQLTRACE_INCREMENTAL_FLUSH_SLEEP was 4000 at the time of the application end. The ASYNC_NETWORK_IO was at 122, giving us a wait ratio of 0.03.

The “problem” resulting in the real issue is: My application takes 4 seconds to run – without any feedback to the user. Not many users are comfortable with that. The “solution” is to uncomment the Console.Writeline() line. (I actually also removed the int a… line, in order to reading the same amount of objects.)

Results was amazing! I could follow the progress of the application as it looped through my rows. When the application was ready, the SQLTRACE_INCREMENTAL_FLUSH_SLEEP had reached 120024! Yes that’s correct! Two minutes of wonderful interaction 🙂 And the ASYNC_NETWORK_IO (the time SQL Server waited for my application to get the next row) was 120201. That is a ratio of  1.0015.

The server indicates that a “slow” application has made the server wait a lot! So what should you do?

Sometimes you have to choose between the unresponsiveness and the slowness, but sometimes you can get the best of the two worlds. You can try to update the screen every 10000 row, or even every 50000 row. Even with the code overhead, this application completed in virtually the same time as the blazing fast one. The difference was ASYNC_NETWORK_IO waited for 160 ms, resulting in a  0.04 ratio. Still acceptable, and the application (randomly) outputted data, making it seem more responsive.

“Optimal code fragment” replacing the while(rdr.Read()) statement:

int count = 0;
while (rdr.Read())
int a = rdr.GetInt32(0);
if (count % 50000 == 0)

Hopefully you’ll be able to identify some issues with these samples.

Certification Rush

1 Comment

Just hours ago I did my seventh certification in four days. Mr Brain is ready for some Christmas. The guys at Informator, Malmö sponsored my certification frenzy (thanks Acke) so I could do two certs per day, between 8 and 10, before the full time consulting started.

Result was OK. Not perfect scores, but still passing score on all 7 SQL Server 2012 certifications. Tonight I’ll celebrate with friends and tomorrow it’ll be business as usual 🙂