如何在C#中以特定的吞吐量调用我的方法?

问题描述 投票:0回答:2

我正在做一些性能测试,所以想以我可以控制的特定吞吐量调用我的方法。通过这种方式,我可以生成一些负载并弄清楚它在各种吞吐量下的行为。

例如:我需要从多个线程中以大约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
    }
}

我想在一段时间内继续运行此测试,但是在此期间,它应该始终仅以特定的吞吐量调用该方法。

c# multithreading performance-testing
2个回答
1
投票

一种方法是在每个时间段内执行给定的时间量。

创建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);

如果时间较短,此方法将开始于所需的数量以下。


1
投票

假设您启动了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
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.