我正在做一些性能测试,所以想以我可以控制的特定吞吐量调用我的方法。通过这种方式,我可以生成一些负载并弄清楚它在各种吞吐量下的行为。
例如:我需要从多个线程中以大约doIOStuff
的速率调用我的x requests per second
方法,其中x大多小于2000,但是在这种情况下,实际上并不重要。它不一定是准确的,所以有一定的出错空间,但是总体思路是,我需要确保在y秒的滑动窗口中,方法doIOStuff
的执行次数不超过x次。
以下是我在3个不同线程中创建的代码,该代码并行调用doIOStuff
方法,但无法弄清楚如何对每秒x个请求的方法进行速率限制。有什么简单的方法可以控制吗?
class Program
{
static void Main(string[] args)
{
var tasks = new List<Task>();
for(int i = 0; i< 100; i ++)
tasks.Add(Task.Factory.StartNew(() => doIOStuff(), i));
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads complete");
}
// how to call this method at a particular rate?
static void doIOStuff()
{
// do some IO work
}
}
我想在一段时间内继续运行此测试,但是在此期间,它应该始终仅以特定的吞吐量调用该方法。
一种方法是在每个时间段内执行给定的时间量。
创建2000个Action
类型的实例,这些实例将表示DoIOStuff
方法。然后尝试通过此操作启动2000个任务,但只有您可以在1秒内完成它(TakeWhile
)。
var period = TimeSpan.FromSeconds(1);
var maxAmountOfCalls = 2000;
var methods = Enumerable.Range(0, maxAmountOfCalls)
.Select(_ => doIOStuff)
.ToArray();
var watch = new Stopwatch();
watch.Start();
var tasks = methods
.Select(method => Task.Run(method))
.TakeWhile(task => watch.Elapsed < period)
.ToArray();
watch.Stop();
await Task.WhenAll(tasks);
如果时间较短,此方法将开始于所需的数量以下。
假设您启动了n个线程,并且每秒最多需要m个调用。这可以通过让每个线程每秒生成0到1之间的随机数,即k次,并且仅当生成的数量小于m / n / k]时才调用IO方法来实现。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp7
{
class Program
{
const int m_threads = 100;
const int n_throughput = 2000;
const int k_toss_per_second = 2000; // Note that k_toss_per_second x should be m_threads >= n_throughput
static void Main(string[] args)
{
var tasks = new List<Task>();
for (int i = 0; i < m_threads; i++)
tasks.Add(Task.Factory.StartNew(() => doIOStuff()));
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads complete");
}
static void callDoIOStuff()
{
int sleep_time = (int) (1000 * 1.0d / k_toss_per_second);
double threshold = (double) n_throughput / m_threads / k_toss_per_second;
Random random = new Random();
while (true) {
Thread.Sleep(sleep_time);
if (random.NextDouble() < threshold)
doIOStuff();
}
}
// how to call this method at a particular rate?
static void doIOStuff()
{
// do some IO work
}
}
}