【问题标题】:Guava RateLimiter running too oftenGuava RateLimiter 运行太频繁
【发布时间】:2017-04-11 15:15:44
【问题描述】:

我在使用 Guava RateLimiter 时遇到问题。我使用 RateLimiter.create(1.0) (“每秒 1 个许可”)创建 RateLimiter,并在每个周期调用 rateLimiter.acquire(),但是当我测试运行时,我得到以下结果:

Average: 1232.0 Diff since last: 2540
Average: 1180.0 Diff since last: 258
Average: 1159.0 Diff since last: 746
Average: 1151.0 Diff since last: 997
Average: 1144.0 Diff since last: 1004

Average 是它平均休眠的毫秒数,而 diff 是自上次打印以来经过的毫秒数。平均来说没关系,它不允许我的代码每秒运行超过一次。但有时(如您所见)它每秒运行一次以上。

你知道为什么吗?我错过了什么吗?

产生上述输出的代码:

private  int numberOfRequests;
private Date start;
private long last;
private boolean first = true;
private void sleep() {
    numberOfRequests++;
    if(first) {
        first = false;
        start = new Date();
    }

    rateLimiter.acquire();

    long current = new Date().getTime();
    double num = (current -start.getTime()) / numberOfRequests;
    System.out.println("Average: "+ num + " Diff since last: " + (current - last));
    last = current;
}

【问题讨论】:

  • 请发布生成此输出的代码的MCVE
  • @AndyTurner 我已经用产生输出的代码更新了问题。
  • 好的,马上跳出来的一件事是你不应该使用System.getCurrentTimeMillis()new Date() 在内部使用)来测量经过的时间 - 请参阅 KevinB 的答案stackoverflow.com/a/1776053/3788176 - 你可以'实际上并不依赖于它单调增加。你应该改用System.nanoTime()
  • code.google.com/p/guava-libraries/source/browse/guava/src/com/…RateLimiter使用的算法在源码中有相当详细的描述。
  • 我明白了!感谢您指出时间问题。在其他项目中也很有用!我已经阅读了源代码,但没有找到问题的根源。会再试一次! @AndyTurner

标签: java guava


【解决方案1】:

您的基准似乎存在缺陷 - 当我尝试复制它时,我发现非常接近每秒一次采集。这是我的基准:

public class RateLimiterDemo {
  public static void main(String[] args) {
    StatsAccumulator stats = new StatsAccumulator();
    RateLimiter rateLimiter = RateLimiter.create(1.0);
    rateLimiter.acquire(); // discard initial permit
    for (int i = 0; i < 10; i++) {
      long start = System.nanoTime();
      rateLimiter.acquire();
      stats.add((System.nanoTime() - start) / 1_000_000.0);
    }
    System.out.println(stats.snapshot());
  }
}

样本运行打印:

Stats{count=10, mean=998.9071456, populationStandardDeviation=3.25398397901304, min=989.303887, max=1000.971085}

那里的差异几乎都归因于基准开销(填充StatsAccumulator 并计算时间增量)。

即使是这个基准也有缺陷(尽管我认为它不那么如此)。创建accurate benchmark非常困难,简单的综合基准测试通常要么不准确,要么更糟糕的是不能反映在生产环境中测试的代码的实际性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多