r-lib / R6

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

Memory management with shared members #145

Closed J-Sward closed 6 years ago

J-Sward commented 6 years ago

I am unclear on how memory management is implemented with R6 objects that contain shared members. I have included a simple case where the class has two fields, each is instantiated with a large vector to illustrate changes in memory used. Both a private and a shared member of unequal sizes are created, although when the object is destroyed, it appears that its shared member persists in memory.

Since the environment variables are shared across all instances of the objects, it makes sense that these are not destroyed when any one of the objects is destroyed. However, when all objects of the class are destroyed I would like to clean up the shared data as well (without wiping everything out with rm(list = ls()). I have tried assigning these shared members NULL in finalize, and removing them altogether (neither of which worked). I can only guess that the environment variables, unmoored from their defining object, need to be accessed/removed directly.

Any help would be greatly appreciated.

rm(list = ls()) library(pryr)

TEST_CLASS <- 
  R6Class("TEST_CLASS",
          public = list(
            initialize = function(){
              private$..pm <- 1:1e6 #about 4MB
              private$shared$sm <- 1:2e6 #about 8MB
            }
            # ,
            # finalize = function(){
            #   #rm(private$..pm)
            #   private$shared$sm <- NULL
            # }
          ),
          private = list(
            ..pm = NA,
            shared = {
              e1 = new.env()
              e1$sm = NA
              e1
            }   
          ),
          active = list(
            getmember = function(){
              return(private$..pm)
            }
          )
  ) 
mem_used()
mem_change(a <- TEST_CLASS$new())
mem_change(b <- TEST_CLASS$new())
mem_change(rm(a))
mem_change(rm(b))
mem_used()
wch commented 6 years ago

In R, memory is not freed until a garbage collection event happens. This is normally semi-random, but you can force it to happen if you run gc().

wch commented 6 years ago

After running your code, there are two things that I've noticed:

> ls(all=T)
[1] ".Random.seed" "e1"           "TEST_CLASS"  

In R, putting code in curly braces does not automatically make for local variables.