У меня есть пакет R, в котором в настоящее время используется система класса S3
, с двумя разными классами и несколькими методами для общих функций S3, таких как plot
, logLik
и update
(для обновления формулы модели). Поскольку мой код стал более сложным со всеми проверками достоверности и структурами if/else
из-за того, что наследования или отправки наследования не было на основе двух аргументов в S3
, я начал думать о преобразовании моего пакета в S4
, Но затем я начал читать о преимуществах и недостатках S3
по сравнению с S4
, и я уже не так уверен. Я нашел сообщение блога R-bloggers об эффективности в S3 vs S4, и, поскольку это было 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
на самом деле бит быстрее. Затем я прочитал вопрос SO об использовании S3
vs S4
, что было в значительной степени в пользу S3
. Особенно ответ @joshua-ulrich заставил меня возражать против S4
, поскольку он сказал, что
для любого изменения слота требуется полная копия объекта
Это кажется большой проблемой, если я рассмотрю мой случай, когда я обновляю свой объект на каждой итерации при оптимизации логарифмической вероятности моей модели. После некоторого поиска я нашел John Chambers post об этой проблеме, которая, кажется, меняется в 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){
[email protected]<-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
Тесты выполняются на R 2.15.2, на 64-битной Windows 7. Итак, здесь S4
явно медленнее.