do.call
is always going to be slower than calling a function directly, because it has to go through your arguments and find the function before calling it. The degree to which it's slower depends on how much additional computation it has in which to amortise this overhead.
> system.time(for(i in 1:1e6) do.call(rnorm, list(100)))
user system elapsed
13.55 0.00 13.58
> system.time(for(i in 1:1e6) rnorm(100))
user system elapsed
11.40 0.00 11.42
whereas:
> system.time(for(i in 1:1e2) do.call(rnorm, list(1e6)))
user system elapsed
9.14 0.00 9.15
> system.time(for(i in 1:1e2) rnorm(1e6))
user system elapsed
9.14 0.00 9.14
In addition, some of your slowdown is due to your regex'ing and other string manipulation which is unrelated to how fast do.call
inherently is. While fast because it's running on trivially small input, it's still needlessly complicated. Why not just do this:
test <- function(distrib, ..., N=1e6)
lapply(seq(N), function(x) distrib(...))
test(rnorm, 100, 1, 10)
or this:
test <- function(call, N=1e6)
{
call <- substitute(call)
lapply(seq(N), function(...) eval.parent(call))
}
test(rnorm(100, 1, 10))