Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r shiny memory leak #1551

Closed
markL0 opened this issue Jan 20, 2017 · 4 comments
Closed

r shiny memory leak #1551

markL0 opened this issue Jan 20, 2017 · 4 comments

Comments

@markL0
Copy link

markL0 commented Jan 20, 2017

Hello, I have got two problems with the following App which plots every second 32 random series.
First, there is a memory leak and second, getting the coordinates only works for points in the middle of the plot.
Can anyone help me? Thank you!
#################################
global.R:
library("pryr")
library("shiny")
plots <- as.list(seq(32))
cols <- 4
numPlots <- length(plots)
nVec <- t(1:numPlots)
##################################
ui.R:
ui <- basicPage(
plotOutput("plot1", click = "plot_click",height=1200,width=2500),
verbatimTextOutput("info")
)
##################################
server.R:
server <- function(input, output) {
observe({ invalidateLater(1000)
output$plot1 <- renderPlot({
layout(matrix(seq(1, cols * ceiling(numPlots/cols)), ncol = cols, nrow = ceiling(numPlots/cols),byrow=F))
lapply(nVec,function(i){plot(rnorm(500),type="l",main=i,ylab="")})
print(mem_used())
})
})

output$info <- renderText({paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)})
}

@daattali
Copy link
Contributor

You can reproduce this with much simpler code (the more minimal the example, the better, because it's easier to isolate the "bug" and see which part causes a problem). For example:

library("shiny")

ui <- basicPage(
  actionButton("go", "Go"),
  plotOutput("plot")
)

server <- function(input, output) {
  observe({
    input$go
    output$plot <- renderPlot({
      
      print(pryr::mem_used())
      plot(rnorm(1000))
    })
  })
}

shinyApp(ui,server)

However, this code is the wrong way to use reactivity. Doing this pattern - defining an output inside an observe() - is something that many people do, but is not the right approach. Here is how I would change my sample code to use reactivity correctly:

library("shiny")

ui <- basicPage(
  actionButton("go", "Go"),
  plotOutput("plot")
)

server <- function(input, output) {
  output$plot <- renderPlot({
    input$go
    print(pryr::mem_used())
    plot(rnorm(1000))
  })
}

shinyApp(ui,server)

Now the memory problem is solved.

@jcheng5 in the workshop last week people asked me why defining outputs in observers is so bad and if it causes any problems other than "it's theoretically wrong". I believe I finally have an answer of when/how it can be bad :)

@wch
Copy link
Collaborator

wch commented Jan 20, 2017

This could be the same as #931, which we thought was fixed, but perhaps it's still a problem.

@markL0
Copy link
Author

markL0 commented Jan 20, 2017

Thank you very much for the fast answers.

The following fixes my first problem:

server <- function(input, output) {

obs<-observe(

      output$plot1 <- renderPlot({invalidateLater(1000)
                                  layout(matrix(seq(1, cols * ceiling(numPlots/cols)), ncol = cols, nrow = ceiling(numPlots/cols),byrow=F))
                                  lapply(nVec,function(i){plot(rnorm(500),type="l",main=i,ylab="")})
                                  print(mem_used())
     
      }))

output$info <- renderText({paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)})
}

Any suggestions to solve the clicking problem with 32 plots?

@jcheng5
Copy link
Member

jcheng5 commented Jan 20, 2017

Take away the obs <- observe() and just declare output$plot1 <- ... and output$info <- ... directly in the server function.

@daattali this pattern is not just stylistically wrong, it will give you the wrong behavior in some cases. https://gist.github.com/jcheng5/3250c4f23b7c141d6907a08b6ddfb36e You might expect this example to only update the output when the Recalculate button is pushed. But it won't, it'll happen every time input$n changes.

For the 32 plots, this approach probably won't work. Base graphics doesn't give us enough metadata about what was plotted to let us know about more than one of your sub-plots. If you can use ggplot2 with faceting, that would probably work; or a grid of plotOutput might work too.

@jcheng5 jcheng5 closed this as completed Jan 20, 2017
paulovcmedeiros added a commit to Hirlam/obsmon that referenced this issue Feb 25, 2021
As suspected in the previous commit, the issue was indeed related to
setting "output" values inside shiny observers. This is a known issue
in shiny. See, for instance, the discussions at
<rstudio/shiny#1551>
and
<https://groups.google.com/forum/#!msg/shiny-discuss/RWmXg3Vscgo/kYlgLef1BAAJ>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants