我有一个 R 包,它当前使用S3
类系统,有两个不同的类和几种用于通用 S3 函数的方法,如plot
,logLik
和update
(用于模型公式更新)。if/else
由于没有基于 in 中的两个参数的继承或分派,我的代码在所有有效性检查和结构中变得更加复杂S3
,我开始考虑将我的包转换为S4
. S3
但后来我开始阅读vs的优缺点S4
,我不再那么确定了。我发现了关于 S3 与 S4 效率问题的R-bloggers 博客文章,就像 5 年前一样,我现在测试了同样的事情:
library(microbenchmark)
setClass("MyClass", representation(x="numeric"))
microbenchmark(structure(list(x=rep(1, 10^7)), class="MyS3Class"),
new("MyClass", x=rep(1, 10^7)) )
Unit: milliseconds
expr
structure(list(x = rep(1, 10^7)), class = "MyS3Class")
new("MyClass", x = rep(1, 10^7))
min lq median uq max neval
148.75049 152.3811 155.2263 159.8090 323.5678 100
75.15198 123.4804 129.6588 131.5031 241.8913 100
所以在这个简单的例子中,S4
实际上要快一点。然后我阅读了关于使用vs的SO 问题,这非常有利于. 特别是@joshua-ulrich 的回答让我怀疑,因为它说S3
S4
S3
S4
任何插槽更改都需要完整的对象副本
如果考虑到我在优化模型的对数似然时在每次迭代中更新对象的情况,那感觉就像一个大问题。经过一番谷歌搜索后,我发现John Chambers 发布了关于这个问题的帖子,这似乎在 R 3.0.0 中发生了变化。
因此,尽管我觉得S4
在我的代码中使用类来提高清晰度(例如从主模型类继承的更多类)以及有效性检查等是有益的,但我现在想知道在以下方面是否值得所有工作表现?S3
那么,在性能方面,和之间是否存在真正的性能差异S4
?我还应该考虑其他一些性能问题吗?或者甚至可以对这个问题说些什么?
编辑:正如@DWin 和@g-grothendieck 所建议的,上述基准测试没有考虑现有对象的插槽被更改的情况。所以这是另一个与真实应用程序更相关的基准(示例中的函数可以是模型中某些元素的 get/set 函数,在最大化对数似然时会改变):
objS3<-structure(list(x=rep(1, 10^3), z=matrix(0,10,10), y=matrix(0,10,10)),
class="MyS3Class")
fnS3<-function(obj,a){
obj$y<-a
obj
}
setClass("MyClass", representation(x="numeric",z="matrix",y="matrix"))
objS4<-new("MyClass", x=rep(1, 10^3),z=matrix(0,10,10),y=matrix(0,10,10))
fnS4<-function(obj,a){
obj@y<-a
obj
}
a<-matrix(1:100,10,10)
microbenchmark(fnS3(objS3,a),fnS4(objS4,a))
Unit: microseconds
expr min lq median uq max neval
fnS3(objS3, a) 6.531 7.464 7.932 9.331 26.591 100
fnS4(objS4, a) 21.459 22.393 23.325 23.792 73.708 100
基准测试是在 64 位 Windows 7 上的 R 2.15.2 上执行的。所以这里S4
显然更慢。