Shiny R reactivevalues memory leak

819 Views Asked by At

I'm trying to understand why a cycling use of shiny's reactivevalues causes it to use more memory. The context is a user interface with the option to automate a given strategy. The example below is based on the St. Petersburg paradox. I appreciate that it may be better practice to place the entire automation process in a seperate function file but I would like to understand why the reactive object increases in size and if there is a more immediate work around.

The example below will print out the amount of memory values is using on the disk. There is no increase in size to the list saved to it.

library(shiny)
library(pryr)


server=shinyServer(function(input, output) {

  values=reactiveValues(win=0,
                        total=1000,
                        gamble=0,
                        stick=0,
                        outcome=0,
                        auto.counter=0
                        )


  #############################################
  # update action from buttons
  observe({
    if(!is.null(input$stick)){
      isolate({
      values$stick=values$stick+1
      })
    }
  })

  observe({
    if(!is.null(input$gamble)){
      isolate({
        values$gamble=values$gamble+1
      })
    }
  })

  #############################################
  ## perform stick action
  observe({
    if(values$stick>0){
      isolate({
        values$total=values$total+2^values$win
        values$auto.counter=max(values$auto.counter-1,0)
        values$win=0
        cat("\nStick:",2^values$win)
        cat("\nReactive values size:",object_size(values))
      })
    }
  })
  # perform gamble action
  observe({
    if(values$gamble>0){
    isolate({
      values$outcome=sample(1:2,1)
      if(values$win==0){
        values$total=values$total-input$entry
      }
      if(values$outcome==1){
        output$print=renderText("Win")
        values$win=values$win+1
      } else {
        output$print=renderText("Lose")
        values$win=0
      }
      cat("\nGamble:",2^values$win)
      cat("\nReactive values size:",object_size(values))
      values$auto.counter=max(values$auto.counter-1,0)

    })
    }
  })

  #############################################
  # automation input
  observe({
    if(input$automate>0){
      isolate({
        values$auto.counter=input$rep
      })
    }
  })

  # if automation on run until auto.counter==0
  observe({
    if(!is.null(values$auto.counter)){
      if(values$auto.counter>0){
        isolate({
          if(2^values$win>input$target){
            values$stick=values$stick+1
          } else {
            values$gamble=values$gamble+1
          }
        })
      }
    }
  })
  #############################################
  # render views
  output$total=renderText({paste("Total winnings:",values$total)})
  output$currentvalue=renderText({paste("Current jackpot:",2^values$win)})
})


ui=shinyUI(fluidPage(

  br(),
  fluidRow(
    column(
      4,
      numericInput(inputId="entry",label="Entry Fee",value=10),
      actionButton(inputId="gamble",label='Gamble'),
      actionButton(inputId="stick",label='Stick'),
      h4("Automate"),
      numericInput(inputId="target",label="Target value",value=20),
      numericInput(inputId="rep",label="Turns",value=10),
      actionButton(inputId="automate",label='Automate')
    ),
    column(
      8,
      textOutput("currentvalue"),
      textOutput("total"),
      textOutput("print")
      )
  )
))


runApp(list(ui=ui,server=server))
0

There are 0 best solutions below