dmr
dmr

Reputation: 55

Delay in bandwidth-throttle/token-bucket (PHP)

I use https://github.com/bandwidth-throttle/token-bucket for queries limited to the external server. My code:

function main() {
    unlink(__DIR__ . "/api.bucket2");
    $storage  = new FileStorage(__DIR__ . "/api.bucket2");
    $rate     = new Rate(3, Rate::SECOND);
    $bucket   = new TokenBucket(3, $rate, $storage);
    $bucket->bootstrap(3);
    $consumer = new BlockingConsumer($bucket);

    for ($i = 0; $i < 12; $i++) {
        $consumer->consume(1);

        work();
    }
}

function work() {
    echo date("d.m.Y H:i:s") . substr((string)microtime(), 1, 4) . "\n";
}

main();

Result:

-bash-4.2$ php -f worker-test.php
03.05.2016 14:26:16.785
03.05.2016 14:26:16.785
03.05.2016 14:26:16.786
03.05.2016 14:26:17.118
03.05.2016 14:26:17.451
03.05.2016 14:26:17.784
...

I expected that the function will be called 3 times per second, but it is not. First 6 calls was in 1 second. if I change "$bucket->bootstrap(3); " on "$bucket->bootstrap(0);", it will be better:

03.05.2016 14:33:34.913
03.05.2016 14:33:35.245
03.05.2016 14:33:35.578
03.05.2016 14:33:35.911
...

but it is still more than 3 per second. What am I doing wrong?

Upvotes: 1

Views: 532

Answers (1)

Markus Malkusch
Markus Malkusch

Reputation: 7878

$bucket->bootstrap(3);

TokenBucket::bootstrap(3) puts three initial tokens into the bucket. Those initial tokens can be consumed instantly. You effectively don't throttle the rate for those first calls.

If you don't want that initial burst, you did correctly bootstrap without any tokens.

03.05.2016 14:33:34.913
03.05.2016 14:33:35.245
03.05.2016 14:33:35.578
03.05.2016 14:33:35.911

but it is still more than 3 per second.

I count 3 per second. Please tolerate this observed variance of ±1ms. In the long run you'll get in average 3 per second.

This ±1ms comes probably from this implementation detail of BlockingConsumer:

// sleep at least 1 millisecond.
usleep(max(1000, $seconds * 1000000));

Upvotes: 2

Related Questions