Медленная отправка метода S4?
В моем классе S4 есть метод, который вызывается много раз. Я заметил, что время выполнения намного медленнее, чем было бы, если бы подобная функция была вызвана независимо. Поэтому я добавил слот с типом «функция» в свой класс и использовал эту функцию вместо метода. В приведенном ниже примере показаны два способа сделать это, и оба они работают намного быстрее, чем соответствующий метод. Кроме того, в примере предполагается, что более низкая скорость метода не связана с тем, что метод должен извлекать данные из класса, поскольку функции работают быстрее, даже если они это делают.
Конечно, такой способ не идеален. Интересно, есть ли способ ускорить отправку метода. Какие-либо предложения?
setClass(Class = "SpeedTest",
representation = representation(
x = "numeric",
foo1 = "function",
foo2 = "function"
)
)
speedTest <- function(n) {
new("SpeedTest",
x = rnorm(n),
foo1 = function(z) sqrt(abs(z)),
foo2 = function() {}
)
}
setGeneric(
name = "method.foo",
def = function(object) {standardGeneric("method.foo")}
)
setMethod(
f = "method.foo",
signature = "SpeedTest",
definition = function(object) {
sqrt(abs(object@x))
}
)
setGeneric(
name = "create.foo2",
def = function(object) {standardGeneric("create.foo2")}
)
setMethod(
f = "create.foo2",
signature = "SpeedTest",
definition = function(object) {
z <- object@x
object@foo2 <- function() sqrt(abs(z))
object
}
)
> st <- speedTest(1000)
> st <- create.foo2(st)
>
> iters <- 100000
>
> system.time(for (i in seq(iters)) method.foo(st)) # slowest by far
user system elapsed
3.26 0.00 3.27
> # much faster
> system.time({foo1 <- st@foo1; x <- st@x; for (i in seq(iters)) foo1(x)})
user system elapsed
1.47 0.00 1.46
> # retrieving st@x instead of x does not affect speed
> system.time({foo1 <- st@foo1; for (i in seq(iters)) foo1(st@x)})
user system elapsed
1.47 0.00 1.49
> # same speed as foo1 although no explicit argument
> system.time({foo2 <- st@foo2; for (i in seq(iters)) foo2()})
user system elapsed
1.44 0.00 1.45
# Cannot increase speed by using a lambda to "eliminate" the argument of method.foo
> system.time({foo <- function() method.foo(st); for (i in seq(iters)) foo()})
user system elapsed
3.28 0.00 3.29