如何以“请求/秒”目标速率生成请求?

时间:2013-04-22 09:01:37

标签: timer load-testing

假设我有一个x个请求/秒的目标,我想连续生成。我的目标是大致相同的间隔 开始,而不是仅仅生成x个请求,然后等待1秒钟,并一遍又一遍地重复整个过程。我没有对这些请求做任何假设,有些可能需要比其他请求更长的时间,这就是为什么我的调度程序线程不会执行请求(或等待它们完成),而是将它们移交给足够大的线程池。

现在,如果x在数百或更低的范围内,我可能会使用.net的TimerThread.Sleep并使用Stopwatch检查实际经过的时间。

但是,如果我想要成千上万或数万,我可以尝试使用高分辨率计时器来维持我的大致相同的间隔方法。但是(在一般操作系统的大多数编程环境中)这意味着需要一些旋转等待的手动编码等等,而且我不确定采取这种方式是否值得。

扩展初始方法,我可以使用Timer来休眠并在每个Timer事件上执行y个请求,监视实现此操作的每秒实际请求数,并在运行时微调y。效果介于“放入所有x请求并等待自启动后经过1秒”之间,我正在尝试不做,并且“在开始下一个请求之前或多或少地等待1 / x秒”。

后者似乎是一个很好的折衷方案,但有什么比这更容易,同时仍然会随着时间推移均匀地分配请求?这必须由不同的人实施数百次,但我找不到关于这个问题的良好参考。

那么最简单的实现方法是什么?

1 个答案:

答案 0 :(得分:1)

一种方法:

首先找到(在Windows上祝你好运)或实施 usleep nanosleep 功能。作为第一步,这可以是(在.net上)一个简单的Thread.SpinWait() / Stopwatch.Elapsed > x组合。如果您想获得更高级别的话,如果时间跨度足够大并且只使用Thread.Sleep()进行微调,请Thread.SpinWait()

完成后,只需采用速率的倒数,您就可以在每个事件之间保持睡眠的时间间隔。您在一个专用线程上执行的基本循环

  1. 火灾事件
  2. 睡眠(睡眠时间)
  3. 然后每个,例如,250ms(或更快的速率),检查实际达到的速率并调整sleepTime间隔,也许用一些平滑来抑制狂野的临时波动,像这样

    newRate = max(1, sleepTime / targetRate * actualRate)
    sleepTime = 0.3 * sleepTime + 0.7 * newRate
    

    这会调整程序和系统中实际发生的事情,并弥补调用事件回调所花费的时间,以及回调在同一个线程上执行的操作等。如果没有这个,你可能会无法获得高精度。

    毋庸置疑,如果您的费率太高而无法使用Sleep但总是必须旋转,一个核心将持续旋转。好消息:我们的机器上有越来越多的核心,所以一个核心越来越重要:)更严重的是,正如你在评论中提到的,如果你的程序实际工作,你的事件生成器将有更少的时间(和需要) )浪费周期。

    查看https://github.com/EugenDueck/EventCannon以获取.net中的概念验证。它大致如上所述实现并作为库完成,因此如果您使用.net,则可以将其嵌入到程序中。