r-lib / R6

Encapsulated object-oriented programming for R
https://R6.r-lib.org
Other
410 stars 56 forks source link

[Feature request] Byte compile class methods during object init #205

Open dselivanov opened 4 years ago

dselivanov commented 4 years ago

I'm wondering if it would be possible to add an option to compile object methods with R's byte compiler during object init?

I have a case when object methods are called each time in a fresh fork of an R session. So they got byte compiled every time before call which leads to significant overhead.

wch commented 4 years ago

Ideally, the methods could be compiled once and then every time an object is instantiated, it receives the pre-compiled method. However, when you copy a function in R and then change its environment, it loses the compiled version of the code.

Here's what happens with a normal function - it gets compiled after being called a few times.

f <- function(x) {
  invisible(x + 1)
}
f
#> function(x) {
#>   invisible(x + 1)
#> }

f(2)
f
#> function(x) {
#>   invisible(x + 1)
#> }

f(2)
f
#> function(x) {
#>   invisible(x + 1)
#> }
#> <bytecode: 0x7fef7c209188>

But copying and changing the environment causes the compiled code to be lost. And for some reason, in this particular case, it doesn't get compiled again, even after calling the function several times. I'm not sure why this is.

g <- f
g
#> function(x) {
#>   invisible(x + 1)
#> }
#> <bytecode: 0x7fef7c209188>

environment(g) <- new.env()
g
#> function(x) {
#>   invisible(x + 1)
#> }
#> <environment: 0x7fef7c48d7e0>

g(2)
g
#> function(x) {
#>   invisible(x + 1)
#> }
#> <environment: 0x7fef7c48d7e0>

g(2)
g
#> function(x) {
#>   invisible(x + 1)
#> }
#> <environment: 0x7fef7c48d7e0>

g(2)
g
#> function(x) {
#>   invisible(x + 1)
#> }
#> <environment: 0x7fef7c48d7e0>

Using .Internal(inspect(g)) will provide more information.

I think it would be possible to have R6 compile the functions each time an object is instantiated, but I'm not eager to implement that. I'd rather have R not lose the bytecode when a function's environment is changed, but I obviously have no control over that. And it's possible that there's a reason for this behavior that I'm missing. It might be helpful to ask about this on the R-devel mailing list.