为什么S3method调度会变慢? S3 dispatch vs manual do.call基准测试

时间:2014-02-04 14:17:41

标签: r performance benchmarking

知道为什么S3 dispatch比大输入的手动do.call慢?

library(rbenchmark)
foo1 <- function(x)UseMethod("foo1",x)
foo1.integer <- function(x)x+1
foo2 <- function(x)do.call(paste("foo2",class(x),sep="."),list(x))
foo2.integer <- function(x)x+1`

小输入

>benchmark(sapply(1:1e3L,foo1))
              test replications elapsed relative user.self sys.self user.child sys.child
1 sapply(1:1000, foo1)          100    0.92        1      0.86        0         NA        NA
>benchmark(sapply(1:1e3L,foo2))
              test replications elapsed relative user.self sys.self user.child sys.child
1 sapply(1:1000, foo2)          100    1.12        1      1.09        0         NA        NA

但是

benchmark(sapply(1:1e4L,foo1))
               test replications elapsed relative user.self sys.self user.child sys.child
1 sapply(1:10000, foo1)          100   29.48        1      27.2     0.03         NA        NA
> benchmark(sapply(1:1e4L,foo2))
               test replications elapsed relative user.self sys.self user.child sys.child
1 sapply(1:10000, foo2)          100   12.39        1     11.75     0.03         NA        NA

修改

> benchmark(foo1 = sapply(1:10000, foo1), foo2 = sapply(1:10000, foo2), replications = 1000)[1:4]
  test replications elapsed relative
 1 foo1         1000  302.00    2.412
 2 foo2         1000  125.21    1.000

1 个答案:

答案 0 :(得分:1)

我不确定你是否真正计划发送,因为sapply还有很多事情要发生。试试这个:

> library(rbenchmark)
>
> foo1 <- function(x)UseMethod("foo1",x)
> foo1.integer <- function(x)x+1
>
> foo2 <- function(x)do.call(paste("foo2",class(x),sep="."),list(x))
> foo2.integer <- function(x)x+1
>
> benchmark(foo1 = foo1(1L), foo2 = foo2(1L), replications = 100000)[1:4]
  test replications elapsed relative
1 foo1       100000    2.81    1.000
2 foo2       100000    3.48    1.238

请注意,当我尝试sapply比较时foo1仍然更快:

> benchmark(foo1 = sapply(1:100, foo1), foo2 = sapply(1:100, foo2), replications = 1000)[1:4]
  test replications elapsed relative
1 foo1         1000    2.31    1.000
2 foo2         1000    2.80    1.212