使用C# Async Await进行负载测试

7

我正在创建一个控制台程序,可以通过模拟多个客户端来测试对缓存的读/写,并编写了以下代码。请帮助我理解:

  • 这是实现多客户端模拟的正确方式吗?
  • 我还能做些什么以使其成为真正的负载测试?
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);
}

1
看起来还行,只是要提一下,WCF和许多其他服务主机会防止来自一个发送者的过多负载,所以即使你从一个单独的计算机轰炸你的服务,其他人也可以轻松访问你的服务。 - Ashkan S
1
可能一些任务可以使用Factory.StartNew进行调度,如果同时存在大量任务,则它们的执行将被延迟。 - cassandrad
2个回答

2
如果很忙,那么显然客户必须等待一段时间才能得到服务。您的程序没有测量这一点,因为秒表在服务请求开始时开始运行。
如果您还想衡量一个请求完成前的平均时间,应该在请求发出时而不是在服务请求时开始计时。
你的程序只从线程池中取线程。如果你启动更多任务,那么有些任务将不得不等待TestAsync开始运行。如果记住Task.Run调用的时间,这个等待时间会被测量到。
除了时间测量上的缺陷之外,您期望同时处理多少个服务请求?您的线程池中是否有足够的空闲线程来模拟这种情况?如果您预计同时有大约50个服务请求,而线程池的大小只有20个线程,那么您永远不会同时运行50个服务请求。反之亦然:如果您的线程池比您预期的同时服务请求数量要大得多,那么您将测量比实际情况更长的时间。
考虑更改线程池中的线程数,并确保没有其他人使用线程池中的任何线程。

感谢您提供详细信息,我会特别注意它们。 - Mrinal Kamboj

2

稍微调整了你的代码,以查看特定时间有多少个线程。

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
    );
}

结果是:如果不使用提示,在虚拟机内我可以同时运行2到10个线程。有了提示,可以达到100个。而在实际机器上,我可以看到一次性启动1000个线程。进程资源管理器确认了这一点。这里提供的提示有些详细信息可能会有帮助。


非常感谢提供这个有趣的信息,特别是关于确保每个线程在单独的客户端上调用而不是计划调用的提示。 - Mrinal Kamboj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接