Is S4 method dispatch slow?

前端 未结 2 1046
别跟我提以往
别跟我提以往 2020-12-29 11:37

My S4 class has a method that is called many times. I noticed that the execution time is much slower than it would be if a similar function was called independently. So I ad

相关标签:
2条回答
  • 2020-12-29 12:21

    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?

    0 讨论(0)
  • 2020-12-29 12:21

    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.

    0 讨论(0)
提交回复
热议问题