Use ratelimitr to limit the rate at which functions are called. A
rate-limited function that allows n
calls per
period
will never have a window of time of length
period
that includes more than n
calls.
library(ratelimitr)
f <- function() NULL
# create a version of f that can only be called 10 times per second
f_lim <- limit_rate(f, rate(n = 10, period = 1))
# time without limiting
system.time(replicate(11, f()))
## user system elapsed
## 0.001 0.000 0.001
## user system elapsed
## 0.008 0.000 1.045
Published rate limits often have multiple types of limits. Here is an example of limiting a function so that it never evaluates more than 10 times per .1 seconds, but additionally never evaluates more than 50 times per 1 second.
f_lim <- limit_rate(
f,
rate(n = 10, period = .1),
rate(n = 50, period = 1)
)
# 10 calls do not trigger the rate limit
system.time( replicate(10, f_lim()) )
## user system elapsed
## 0 0 0
# note that reset does not modify its argument, but returns a new
# rate-limited function with a fresh timer
f_lim <- reset(f_lim)
system.time( replicate(11, f_lim()) )
## user system elapsed
## 0.001 0.000 0.138
# similarly, 50 calls don't trigger the second rate limit
f_lim <- reset(f_lim)
system.time( replicate(50, f_lim()) )
## user system elapsed
## 0.004 0.001 0.552
## user system elapsed
## 0.006 0.001 1.043
To limit a group of functions together, just pass
limit_rate
a list of functions instead of a single
function. Make sure the list is named, the names will be how you access
the rate-limited versions of the functions:
f <- function() "f"
g <- function() "g"
h <- function() "h"
# passing a named list to limit_rate
limited <- limit_rate(
list(f = f, g = g, h = h),
rate(n = 3, period = 1)
)
# now limited is a list of functions that share a rate limit. examples:
limited$f()
## [1] "f"
## [1] "g"
The new functions are subject to a single rate limit, regardless of which ones are called or in what order they are called.
# the first three function calls should not trigger a delay
system.time(
{limited$f(); limited$g(); limited$h()}
)
## user system elapsed
## 0.001 0.001 0.002
limited <- reset(limited)
# but to evaluate a fourth function call, there will be a delay
system.time({
limited$f()
limited$g()
limited$h()
limited$f()
})
## user system elapsed
## 0.001 0.000 1.039