0

Basically, I want to stopwatch against an async API call to Google BigQuery. I meant to design the test run in two modes: (1)single thread mode -- call the API, wait for it to finish its task and then fire the next call. (2) multiple thread mode -- start multiple calls through Task.Run, then wait for them all. The test result is very confused, according to the stopwatch. In the first mode, each API call finishes its task within around 300ms, but in the second mode, except for the first few calls, each API call takes over 10 seconds. That's a huge difference! (Windows 8.1 Pro, 8GB RAM, 2-cores CPU)

It could be something on the Google BigQuery side, but besides that possibility, I want to ensure that I'm using stopwatch correctly, or I mean I'm measuring what I meant to measure. Am I?

Here's the code:

 static void Main(string[] args)
    {
       // SingleThreadMode();
        MultiThreadMode();
    }

 private static void SingleThreadMode()
    {
        var batch = ReadOneBatchInArrays();
        for (int i = 0; i < 100; i++)
        {
            try
            {
                Task.Run(async () => { await InsertAsync("T20150624", batch, InsertId); }).Wait(-1);
            }
            catch (AggregateException e)
            {
                foreach (var exception in e.InnerExceptions)
                {
                    Console.WriteLine(exception);
                }
            }
        }
        Console.WriteLine("End");
        Console.ReadLine();
    }

private static void MultiThreadMode()
    {
        var batch = ReadOneBatchInArrays();
        IList<Task> tasks = new List<Task>();
        for (int i = 0; i < 100; i++)
        {
            try
            {
                tasks.Add(Task.Run(async () => { await InsertAsync("T20150624", batch, InsertId); }));
            }
            catch (AggregateException e)
            {
                foreach (var exception in e.InnerExceptions)
                {
                    Console.WriteLine(exception);
                }
            }
        }
        Task.WaitAll(tasks.ToArray(),-1);
        Console.WriteLine("End");
        Console.ReadLine();
    }

Stopwatch in the InsertAsync:

Stopwatch stopwatch = Stopwatch.StartNew();
TableDataInsertAllResponse response = await BqService.Tabledata.InsertAll(request, ProjectId, DatasetId, tableId).ExecuteAsync(); 
stopwatch.Stop();
Logger.Trace("BigQuery.InsertAll#Back|row count|milliseconds~{0}~{1}", rowList.Count, stopwatch.ElapsedMilliseconds);

Solve Thanks very much to the following answer. I ended up add several lines in my app.config, and it solves this problem.

<system.net>
<connectionManagement>
    <add address="*" maxconnection="2000" />
</connectionManagement>
</system.net>
foxwendy
  • 2,819
  • 2
  • 28
  • 50

1 Answers1

2

You are most likely running into the concurrent connection limit in .Net as illustrated in this question: Max number of concurrent HttpWebRequests.

The maximum number of concurrent requests to a single host is limited. So what is happening is the first couple of requests go through immediately, but once the limit is hit the latter requests start blocking and waiting until the first requests finish.

Community
  • 1
  • 1
shf301
  • 31,086
  • 2
  • 52
  • 86