Feature/refill rate limiter (rate limiter only) #1370
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a pull request for the ticket #1138
As discussed on #1139 this pull request is only for the Refill Rate Limiter implementation. Thus it contains only the rate limiter implementation, its config, unit tests and benchmarks.
The registry and the code to make it feasible to have a more generic registry will be on another branch.
How it works
The main concept is to have a bucket of permissions allocated with a max number of permissions (more permissions than that cannot be accumulated or served).
An integer keeps track of the permissions accumulated over time but the max value is limited by the capacity described above. Also another number acts as a time index - up to which time we calculated the permissions.
At startup we can have some permissions pre-assigned.
When a permission is requested the first step is to subtract the existing permissions from the request ones
If the result is positive the request can be served immediately with the permissions we already have
and the state will be updated with the remaining permissions (the result of the previous calculation).
If the result is negative, we need to see if enough time has passed to fulfil those requests.
We calculate the difference of the current Nanos minus the nanos the state we had back when we last updated (time index).
The time that has passed is caped by the time needed to fill up the maximum number of requests. So no matter how much time has passed we shall be limited by the max permissions (so no overflow or extra permissions given).
If we are on a max permission scenario (we have accumulated the maximum of permissions), we remove the extra permits needed from the max permissions and we update the state with the permissions left and set the current nano time to the time index.
If we have not accumulated the max permissions, we check If the time we have accumulated is bigger or equal to the time needed to serve the extra requests.
If the right time has been accumulated we fulfil the request and the time index is updated with 0 permissions and add to the time-index the time that was needed to accumulate the permissions.
If the time needed is exceeds the accumulated time then we extract the difference and this is the time to wait for the permissions to be released. The state will have 0 permissions and the time index will be at the future. It will be the current index plus the time needed as a whole to fulfil the extra permissions.
If the time needed will cause a timeout no change to the state will happen.
Benchmarks
The benchmarks (can be download from here)
The menckmark-all.*.txt files contain the benchmarks with all the rate limiters on the branch (atomic,refill,semaphore).
Since the atomic rate limiter had some changes (slightly changed) I did some benchmarks before and after only with the atomic rate limiter.
The atomic-before.*.txt files contain the benchmarks with the atomic rate limiter on the master branch.
The atomic-after.*.txt files contain the benchmarks with the atomic rate limiter on the pr branch.
Due to the Refill Rate limiter sharing same code parts with the atomic rate limiter I have some benchmarks only with the refill rate limiter.