使用 C# Async Await 进行负载测试
Load Test using C# Async Await
我正在创建一个控制台程序,它可以通过模拟多个客户端来测试对缓存的读/写,并编写了以下代码。请帮助我理解:
- 多客户端模拟的实现方式是否正确
- 我还能做些什么才能使其成为真正的负载测试
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);
}
稍微调整了您的代码以查看我们在特定时间有多少个线程。
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 证实了这一点。 hint 的一些详细信息会有所帮助。
如果它很忙,那么显然您的客户必须等待一段时间才能满足他们的请求。您的程序不会对此进行测量,因为您的秒表会在服务请求启动时启动 运行ning。
如果您还想测量请求完成前的平均时间发生了什么,您应该在请求发出时启动秒表,而不是在请求得到服务时。
您的程序只从线程池中获取线程。如果您启动更多任务然后有线程,一些任务将不得不等待 TestAsync 启动 运行ning。如果您记得调用 Task.Run 的时间,就会计算出此等待时间。
除了时间测量上的缺陷外,您预计同时有多少服务请求?你的线程池中是否有足够的空闲线程来模拟这个?如果您期望同时有大约 50 个服务请求,而您的线程池的大小只有 20 个线程,那么您永远不会 运行 同时有 50 个服务请求。反之亦然:如果您的线程池比预期的同时服务请求数量大得多,那么您测量的时间将比实际情况长。
考虑更改线程池中的线程数,并确保没有其他人使用池中的任何线程。
我正在创建一个控制台程序,它可以通过模拟多个客户端来测试对缓存的读/写,并编写了以下代码。请帮助我理解:
- 多客户端模拟的实现方式是否正确
- 我还能做些什么才能使其成为真正的负载测试
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);
}
稍微调整了您的代码以查看我们在特定时间有多少个线程。
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 证实了这一点。 hint 的一些详细信息会有所帮助。
如果它很忙,那么显然您的客户必须等待一段时间才能满足他们的请求。您的程序不会对此进行测量,因为您的秒表会在服务请求启动时启动 运行ning。
如果您还想测量请求完成前的平均时间发生了什么,您应该在请求发出时启动秒表,而不是在请求得到服务时。
您的程序只从线程池中获取线程。如果您启动更多任务然后有线程,一些任务将不得不等待 TestAsync 启动 运行ning。如果您记得调用 Task.Run 的时间,就会计算出此等待时间。
除了时间测量上的缺陷外,您预计同时有多少服务请求?你的线程池中是否有足够的空闲线程来模拟这个?如果您期望同时有大约 50 个服务请求,而您的线程池的大小只有 20 个线程,那么您永远不会 运行 同时有 50 个服务请求。反之亦然:如果您的线程池比预期的同时服务请求数量大得多,那么您测量的时间将比实际情况长。
考虑更改线程池中的线程数,并确保没有其他人使用池中的任何线程。