rstudio / shiny

Easy interactive web applications with R
https://shiny.posit.co/
Other
5.36k stars 1.87k forks source link

Shiny is not releasing memory #3953

Open apalacio9502 opened 10 months ago

apalacio9502 commented 10 months ago

Hello,

We have detected that shiny app is not releasing memory when the user session ends, which we believe is a similar problem to this bug https://github.com/rstudio/plumber/issues/938 that we have posted.

We understand that in this case the problem is that R memory usage is growing because some objects are not released in a specific case.

We have tried to solve the problem by adding a gc() in the session$onSessionEnded, however it has not generated the expected result as we obtained with the postserialize in the plumber apis. We are not experts on how shiny destroys reactive objects, but we believe that this is where the problem lies because we assume that onSessionEnded happens after shiny destroys the objects.

We do not know if there is another way to implement gc() so that the memory is freed when the user session ends

Reading previous bugs we have found this bug https://github.com/rstudio/shiny/issues/1253 which we understand is similar

This problem has an impact when you always have a process active. This becomes relevant when you have the apps in a productive environment with high demand (hosted in posit connect for example).

Regards,

ismirsehregal commented 9 months ago

I'm observing similar behaviour with one of my "bigger" apps and tried to create a reproducible example to show it. However, it turns out using my example the memory is released after closing a session (even without calling gc() on session end). Accordingly I guess the issue has a different origin:

library(DT)
library(pryr)
library(shiny)

current_mem_used_pretty_size <- reactive({
  invalidateLater(1000L)
  format(structure(mem_used(), class="object_size"), units="auto", standard="SI")
})

ui <- fluidPage(
  uiOutput("start_new_session"),
  textOutput("memory_used_session_start"),
  textOutput("memory_currently_used"),
  div(actionLink("close_session", "Close this session"), style = "margin-bottom:20px;"),
  DTOutput("example_table")
)

server <- function(input, output, session) {
  observeEvent(input$close_session, {
    session$close()
  })
  example_data <- reactive({
    data.frame(replicate(100L, runif(10000L)))
  })
  output$example_table <- renderDT({example_data()}, options = list(scrollX = TRUE))
  output$start_new_session <- renderUI({
    clientData <- reactiveValuesToList(session$clientData)
    link <- with(clientData, paste0(url_protocol, "//", url_hostname, ":", url_port, url_pathname))
    div(a("Open new session", target="_blank", href = link, title = link), style = "margin-top:10px;")
  })
  output$memory_used_session_start <- renderText({
    mem_used_pretty_size <- format(structure(mem_used(), class = "object_size"), units = "auto", standard = "SI")
    paste0(mem_used_pretty_size, " memory used after starting this session (", session$token, ")")
  })
  output$memory_currently_used <- renderText({
    paste0(current_mem_used_pretty_size(), " memory currently in use (", format(Sys.time(), usetz = TRUE, digits = 0L), ")")
  })
  onStop(function(){
    cat("Stopped session", session$token, "\n")
    # gc(verbose = TRUE)
    print(mem_used())
  })
}

shinyApp(ui, server)

screen

Here a related SO post can be found.

Mkranj commented 5 months ago

Hi, do you still experience these problems? We've also experienced them. Have you found any tips for dealing with memory issues in long running apps?