7

I am creating a console program, which can test read / write to a Cache by simulating multiple clients, and have written following code. Please help me understand:

  • Is it correct way to achieve the multi client simulation
  • What can I do more to make it a genuine load test
void Main()
{

    List<Task<long>> taskList = new List<Task<long>>();

    for (int i = 0; i < 500; i++)
    {
      taskList.Add(TestAsync());
    }

    Task.WaitAll(taskList.ToArray());

    long averageTime  = taskList.Average(t => t.Result);

}

public static async Task<long> TestAsync()
{
    // Returns the total time taken using Stop Watch in the same module
    return await Task.Factory.StartNew(() => // Call Cache Read / Write);
}
svick
  • 236,525
  • 50
  • 385
  • 514
Mrinal Kamboj
  • 11,300
  • 5
  • 40
  • 74
  • 1
    Seems ok, just to mention, WCf and many other service hosts will prevent to much load from one sender, so even if you bombard your service from a single computer, the others can easily access your service. – Ashkan S Aug 04 '16 at 17:58
  • 1
    Probably some tasks could get scheduled with `Factory.StartNew` and their execution will be delayed in case of huge amount of simultaneous tasks. – cassandrad Aug 04 '16 at 19:53

2 Answers2

2

Adjusted your code slightly to see how many threads we have at a particular time.

static volatile int currentExecutionCount = 0;

static void Main(string[] args)
{
    List<Task<long>> taskList = new List<Task<long>>();
    var timer = new Timer(Print, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));

    for (int i = 0; i < 1000; i++)
    {
        taskList.Add(DoMagic());
    }

    Task.WaitAll(taskList.ToArray());

    timer.Change(Timeout.Infinite, Timeout.Infinite);
    timer = null;

    //to check that we have all the threads executed
    Console.WriteLine("Done " + taskList.Sum(t => t.Result));
    Console.ReadLine();
}

static void Print(object state)
{
    Console.WriteLine(currentExecutionCount);
}

static async Task<long> DoMagic()
{
    return await Task.Factory.StartNew(() =>
    {
        Interlocked.Increment(ref currentExecutionCount);
        //place your code here
        Thread.Sleep(TimeSpan.FromMilliseconds(1000));
        Interlocked.Decrement(ref currentExecutionCount);
        return 4;
    }
    //this thing should give a hint to scheduller to use new threads and not scheduled
    , TaskCreationOptions.LongRunning
    );
}

The result is: inside a virtual machine I have from 2 to 10 threads running simultaneously if I don't use the hint. With the hint — up to 100. And on real machine I can see 1000 threads at once. Process explorer confirms this. Some details on the hint that would be helpful.

Community
  • 1
  • 1
cassandrad
  • 3,412
  • 26
  • 50
  • Great thanks for providing an interesting piece of information, especially regarding the hint to ensure that each thread is invoke on separate client, instead of scheduled one – Mrinal Kamboj Aug 05 '16 at 03:12
2

If it is very busy, then apparently your clients have to wait a while before their requests are serviced. Your program does not measure this, because your stopwatch starts running when the service request starts.

If you also want to measure what happen with the average time before a request is finished, you should start your stopwatch when the request is made, not when the request is serviced.

Your program takes only threads from the thread pool. If you start more tasks then there are threads, some tasks will have to wait before TestAsync starts running. This wait time would be measured if you remember the time Task.Run is called.

Besides the flaw in time measurements, how many service requests do you expect simultaneously? Are there enough free threads in your thread pool to simulate this? If you expect about 50 service requests at the same time, and the size of your thread pool is only 20 threads, then you'll never run 50 service requests at the same time. Vice versa: if your thread pool is way bigger than your number of expected simultaneous service requests, then you'll measure longer times than are actual the case.

Consider changing the number of threads in your thread pool, and make sure no one else uses any threads of the pool.

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116