为什么对列表进行分类会减慢length()函数的速度?

Ken*_*oit 4 performance r

我刚刚注意到,通过向class属性添加附加标签(S3)或定义新的父类(S4)来对列表进行分类会大大减慢基本lengths()操作的速度.

这表明我应该在打电话之前总是取消"分类列表" lengths().

任何人都可以

  1. 解释为什么会发生这种情况,和/或

  2. 建议一个更好的解决方案(或解释为什么这并不重要,因为差异只是绝对数字的微秒).

可重现的代码:

# create a list of 1,000 elements with variable letter lengths
mylist <- list()
length(mylist) <- 1000
set.seed(99)
mylist <- lapply(mylist, function(x) sample(LETTERS, size = sample(1:100, size = 1), 
                                            replace = TRUE))

# create an S3 "classed" version
mylist_S3classed <- mylist
class(mylist_S3classed) <- c("myclass", "list")

# create an S4 classed version
setClass("mylist_S4class", contains = "list")
mylist_S4classed <- new("mylist_S4class", mylist)

# compare timings of lengths
microbenchmark::microbenchmark(lengths(mylist),
                               lengths(mylist_S3classed), 
                               lengths(mylist_S4classed),
                               unit = "relative")
## Unit: relative
##                      expr      min       lq     mean    median        uq       max neval
##           lengths(mylist)   1.0000   1.0000   1.0000   1.00000   1.00000   1.00000   100
## lengths(mylist_S3classed) 125.1433 119.3588 103.9747  91.90734  89.56034 291.97767   100
## lengths(mylist_S4classed) 162.4045 155.4870 119.0611 120.20908 111.95417  67.55309   100

## in absolute timings
microbenchmark::microbenchmark(lengths(mylist),
                               lengths(mylist_S3classed), 
                               lengths(mylist_S4classed))
## Unit: microseconds
##                      expr      min        lq       mean    median       uq      max neval
##           lengths(mylist)    6.401    6.9475    9.66612    9.4620   10.577   29.237   100
## lengths(mylist_S3classed)  792.738  851.0895  911.97067  898.0955  939.558 1604.189   100
## lengths(mylist_S4classed) 1050.448 1104.7920 1293.63965 1173.4545 1229.485 6431.130   100
Run Code Online (Sandbox Code Playgroud)

Spa*_*man 5

这个额外时间是R找到正确length功能所需的时间.对于一个普通的旧列表,它非常容易和优化,它可能存储在对象中.得到它,归还它.

对于一个被分类的对象,无论是S3还是S4,R必须找到正确的length函数,因为它length可以被定义为一种方法.所以R必须继续进行搜索,在你的情况下它会随处可见,直到它达到默认值.当它完成时,它花了那些毫秒.

除非你可以告诉你未来的自己,你永远不会length在这些对象上写一个方法,因为你的代码会破坏,所以不要去取消分类以试图加快速度.