使用C#异步Await进行负载测试

本文关键字:负载 测试 Await 异步 使用 | 更新日期: 2023-09-27 18:00:58

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

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

使用C#异步Await进行负载测试

稍微调整一下代码,看看我们在特定时间有多少线程。

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个线程。Process explorer对此进行了确认。提示中的一些细节会有所帮助。

如果它非常繁忙,那么显然您的客户端必须等待一段时间才能为其请求提供服务。您的程序不会对此进行测量,因为当服务请求启动时,您的秒表就会开始运行。

如果你还想衡量在请求完成前的平均时间,你应该在请求发出时启动秒表,而不是在请求得到服务时。

您的程序只从线程池中获取线程。如果启动的任务比线程多,那么在TestAsync开始运行之前,一些任务将不得不等待。如果你还记得调用Task.Run的时间,就会测量这个等待时间。

除了时间测量中的缺陷之外,您预计同时有多少服务请求?线程池中是否有足够的可用线程来模拟这种情况?如果您期望同时运行大约50个服务请求,而线程池的大小只有20个线程,那么您永远不会同时运行50个服务要求。反之亦然:如果你的线程池比预期的同时服务请求数量大得多,那么你会测量到比实际情况更长的时间。

请考虑更改线程池中的线程数,并确保没有其他人使用该池中的任何线程。