Recently I am testing http "requests per second" difference on Threading and Async/Await.
Using Async/Await is always slighty better(~30%) than Threading (2000-3000 requests per second) until I change the httpwebrequest from "GET" to "POST"
Threading version is still normal (~2000-3000 requests per seconds) with high thread amount like 2000 threads
Async/Await version becomes slow and even stuck under high amount of async task situation( ~500 requests per second, some tasks (~1%) do not finish (unreasonable time like 1 minute) although all other tasks were all finished very early)
Please shed some light on this, I can barely think of a reason why this happens.
Here's the function that stuck
using (Stream postStream = await req.GetRequestStreamAsync())
{
await postStream.WriteAsync(bytes, 0, bytes.Length); //This is the function that stuck in async version
}
Here's my test code
public static Amount = 0;
public void StartSync(int threadAmount)
{
Amount = 0;
Thread[] thread = new Thread[threadAmount];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < thread.Length; i++)
{
thread[i] = new Thread(() =>
{
SyncTest();
});
thread[i].IsBackground = true;
thread[i].Start();
}
for (int j = 0; j < thread.Length; j++)
{
thread[j].Join();
}
sw.Stop();
MessageBox.Show("Total requests: " + amount + "\r\nTotal seconds: " + (sw.ElapsedMilliseconds / 1000.0) + "\r\nRequests per second: " + Convert.ToDouble(amount) / (sw.ElapsedMilliseconds / 1000.0));
}
public void StartAsync(int threadAmount)
{
Amount = 0;
Task[] task = new Task[threadAmount];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < threadAmount; i++)
{
task[i] = AsyncTest();
}
await Task.WhenAll(task);
sw.Stop();
MessageBox.Show("Total requests: " + amount + "\r\nTotal seconds: " + (sw.ElapsedMilliseconds / 1000.0) + "\r\nRequests per second: " + Convert.ToDouble(amount) / (sw.ElapsedMilliseconds / 1000.0));
}
public async Task<bool> AsyncTest()
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.google-analytics.com/__utm.gif");
req.Method = "POST";
req.AllowAutoRedirect = false;
byte[] bytes = Encoding.ASCII.GetBytes("test");
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bytes.Length;
using (Stream postStream = await req.GetRequestStreamAsync())
{
await postStream.WriteAsync(bytes, 0, bytes.Length); //This is the function to be investigated. Adding this line slows down async side significantly
}
using (HttpWebResponse res = (HttpWebResponse)await req.GetResponseAsync())
using (Stream responseStream = res.GetResponseStream())
{
StreamReader sr = new StreamReader(responseStream, Encoding.ASCII);
string resp = await sr.ReadToEndAsync();
}
Amount++;
return true;
}
public bool SyncTest()
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.google-analytics.com/__utm.gif");
req.Method = "POST";
req.AllowAutoRedirect = false;
byte[] bytes = Encoding.ASCII.GetBytes("test");
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bytes.Length;
using (Stream oStreamOut = req.GetRequestStream())
{
oStreamOut.Write(bytes, 0, bytes.Length);
}
using (HttpWebResponse webResponse = (HttpWebResponse)req.GetResponse())
{
using (Stream responseStream = webResponse.GetResponseStream())
{
StreamReader sr = new StreamReader(responseStream, Encoding.ASCII);
string resp = sr.ReadToEnd();
}
}
Amount++;
return true;
}
Update 1:
I tested WriteAsync in memorystream with high amount of async tasks but the slow down did not happen
public async Task<bool> AsyncWrite()
{
byte[] bytes = Encoding.ASCII.GetBytes("test");
using (MemoryStream ms = new MemoryStream())
{
await ms.WriteAsync(bytes, 0, bytes.Length);
}
}
Update 2:
I plugged out my router, async version becomes normal, no more stuck. Only with router connected, the weird slow down happens. I cannot explain why this happened to async version only but not threading...