Is S4 method dispatch slow?

廉价感情. 提交于 2019-11-30 05:12:12

The cost is in method look-up, which starts from scratch in each iteration of your timing. This can be short-circuited by figuring out method dispatch once

METHOD <- selectMethod(method.foo, class(st))
for (i in seq(iters)) METHOD(st)

This (better method look-up) would be a very interesting and worth-while project; there are valuable lessons learned in other dynamic languages, e.g., inline caching mentioned on Wikipedia's dynamic dispatch page.

I wonder if the reason that you're making many method calls is because of incomplete vectorization of your data representation and methods?

This doesn't help you directly with your problem, but it's much easier to benchmark this sort of stuff with the microbenchmark package:

f <- function(x) NULL

s3 <- function(x) UseMethod("s3")
s3.integer <- function(x) NULL

A <- setClass("A", representation(a = "list"))
setGeneric("s4", function(x) standardGeneric("s4"))
setMethod(s4, "A", function(x) NULL)

B <- setRefClass("B")
B$methods(r5 = function(x) NULL)

a <- A()
b <- B$new()

library(microbenchmark)
options(digits = 3)
microbenchmark(
  bare = NULL,
  fun = f(),
  s3 = s3(1L),
  s4 = s4(a),
  r5 = b$r5()
)
# Unit: nanoseconds
#  expr   min    lq median    uq   max neval
#  bare    13    20     22    29    36   100
#   fun   171   236    270   310   805   100
#    s3  2025  2478   2651  2869  8603   100
#    s4 10017 11029  11528 11905 36149   100
#    r5  9080 10003  10390 10804 61864   100

On my computer, the bare call takes about 20 ns. Wrapping it in a function adds about an extra 200 ns - this is the cost of creating the environment where the function execution happens. S3 method dispatch adds around 3 µs and S4/ref classes around 12 µs.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!