google / guava

Google core libraries for Java
Apache License 2.0
50.01k stars 10.86k forks source link

RateLimiter is not accurate #5296

Open h4yin opened 3 years ago

h4yin commented 3 years ago

@nick-someone Thanks for your reply.

Are you getting 83300 permits per second consistently?

Almost yes.

2020-10-25 15:41:22.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83261 /s
2020-10-25 15:41:23.701 INFO  main (RateLimiterTest.java:29) - Aquired: 82953 /s
2020-10-25 15:41:24.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83287 /s
2020-10-25 15:41:25.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:41:26.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:41:27.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:41:28.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:41:29.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:41:30.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:41:31.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:41:32.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:41:33.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:41:34.701 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:41:35.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83296 /s
2020-10-25 15:41:36.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:41:37.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83303 /s
2020-10-25 15:41:38.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:41:39.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:41:40.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:41:41.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83307 /s
2020-10-25 15:41:42.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83298 /s
2020-10-25 15:41:43.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:41:44.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:41:45.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83297 /s
2020-10-25 15:41:46.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:41:47.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83303 /s
2020-10-25 15:41:48.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:41:49.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83298 /s
2020-10-25 15:41:50.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:41:51.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:41:52.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:41:53.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:41:54.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:41:55.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:41:56.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:41:57.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:41:58.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:41:59.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:42:00.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83299 /s
2020-10-25 15:42:01.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:42:02.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83302 /s
2020-10-25 15:42:03.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83296 /s
2020-10-25 15:42:04.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83306 /s
2020-10-25 15:42:05.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83299 /s
2020-10-25 15:42:06.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:42:07.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:42:08.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:42:09.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:42:10.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:42:11.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83303 /s
2020-10-25 15:42:12.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83305 /s
2020-10-25 15:42:13.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:42:14.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:42:15.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83303 /s
2020-10-25 15:42:16.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83297 /s
2020-10-25 15:42:17.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:42:18.702 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:42:19.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83300 /s
2020-10-25 15:42:20.704 INFO  main (RateLimiterTest.java:29) - Aquired: 83297 /s
2020-10-25 15:42:21.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:42:22.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83295 /s
2020-10-25 15:42:23.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:42:24.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83309 /s
2020-10-25 15:42:25.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83305 /s
2020-10-25 15:42:26.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83308 /s
2020-10-25 15:42:27.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:42:28.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83274 /s
2020-10-25 15:42:29.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:42:30.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:42:31.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83280 /s
2020-10-25 15:42:32.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:42:33.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83269 /s
2020-10-25 15:42:34.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83297 /s
2020-10-25 15:42:35.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83294 /s
2020-10-25 15:42:36.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:42:37.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:42:38.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83290 /s
2020-10-25 15:42:39.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83286 /s
2020-10-25 15:42:40.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83278 /s
2020-10-25 15:42:41.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83275 /s
2020-10-25 15:42:42.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83286 /s
2020-10-25 15:42:43.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:42:44.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83295 /s
2020-10-25 15:42:45.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83312 /s
2020-10-25 15:42:46.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:42:47.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:42:48.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:42:49.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:42:50.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83307 /s
2020-10-25 15:42:51.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83295 /s
2020-10-25 15:42:52.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83293 /s
2020-10-25 15:42:53.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83291 /s
2020-10-25 15:42:54.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83304 /s
2020-10-25 15:42:55.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83301 /s
2020-10-25 15:42:56.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83292 /s
2020-10-25 15:42:57.703 INFO  main (RateLimiterTest.java:29) - Aquired: 83295 /s

Have you used something like http://guava.dev/Stopwatch to make sure that your reset loop is triggering correctly once every 1 second?

There is an another way shows the same error.

    private static final Logger logger = LoggerFactory.getLogger(RateLimiterTest.class);

    public static void main(String[] args) {

        long limit = 80000;
        RateLimiter rateLimiter = RateLimiter.create(limit);
        Stopwatch stopwatch = Stopwatch.createStarted();
        long aquired = 0L;
        while (true) {
            if (rateLimiter.tryAcquire()) {
                ++aquired;
            }
            if (aquired == limit) {
                logger.info("Acquire {}, cost: {}ms", aquired, stopwatch.elapsed().toMillis());
                aquired = 0;
                stopwatch.reset().start();
            }
        }
    }
2020-10-25 15:54:57.807 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 961ms
2020-10-25 15:54:58.769 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 955ms
2020-10-25 15:54:59.729 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:00.690 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:01.650 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:02.611 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:03.571 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:04.532 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:05.492 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:06.453 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:07.413 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:08.373 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:09.334 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:10.294 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:11.255 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:12.215 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:13.176 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:14.136 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:15.096 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:16.057 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:17.017 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:17.978 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:18.938 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:19.899 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:20.859 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:21.820 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:22.780 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:23.741 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:24.701 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:25.662 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:26.622 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:27.583 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:28.543 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:29.504 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:30.464 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:31.425 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:32.385 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:33.346 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:34.306 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:35.266 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:36.227 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:37.187 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:38.148 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:39.108 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:40.069 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:41.030 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:41.990 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:42.950 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:43.910 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:44.871 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:45.831 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:46.791 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:47.752 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:48.712 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:49.672 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:50.632 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:51.593 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:52.553 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:55:53.513 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:54.475 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:55.434 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 958ms
2020-10-25 15:55:56.395 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:57.355 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:58.316 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:55:59.276 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:00.237 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:01.197 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:02.157 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:56:03.117 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:56:04.078 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 959ms
2020-10-25 15:56:05.038 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:05.999 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:06.959 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:07.920 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:08.880 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:09.841 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:10.802 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:11.762 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:12.722 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:13.683 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms
2020-10-25 15:56:14.643 INFO  main (RateLimiterTest.java:30) - Acquire 80000, cost: 960ms

Dive into the method final long reserveEarliestAvailable(int requiredPermits, long nowMicros)

    long waitMicros =
        storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
            + (long) (freshPermits * stableIntervalMicros);

For 80000 permitsPerSecond, the double stableIntervalMicros is 12.5, and when freshPermits is 1, the product cast to long is 1 * 12.5 = 12, there is the error 0.5/12.5 = 4%.

Originally posted by @h4yin in https://github.com/google/guava/issues/5290#issuecomment-716116642

h4yin commented 3 years ago

@nick-someone Sorry to bother you. Would you continue this issue. Thanks!

Ahbishek commented 2 years ago

Any update on this issue? Found similar inaccuracy behaviour.