【问题标题】:Memory leak by using observeEvent通过使用 observeEvent 的内存泄漏
【发布时间】:2020-04-04 20:30:08
【问题描述】:

我使用以下代码累积内存。每次我在操作按钮 1 和 2 之间切换时,使用的内存都会增加。

library(ggplot2)
library(shiny)
library(lobstr)

ui <- navbarPage("Test",fluidPage(fluidRow(
                     column(width = 1, actionButton("action_input_1", label = "1")), 
                     column(width = 1, actionButton("action_input_2", label = "2")),
                     column(width = 10, plotOutput("plot", width = 1400, height = 800)))))

server <- function(input, output) {
  # 1
  observeEvent(input$action_input_1, {
    output$plot <- renderPlot({
      plot(rnorm(100))
    })
    print(cat(paste0("mem used 1: ", capture.output(print(mem_used())),"\n")))
  })

  # 2
  observeEvent(input$action_input_2, {
    output$plot <- renderPlot({
      plot(rnorm(1000))
    })
    print(cat(paste0("mem used 2: ", capture.output(print(mem_used())),"\n")))
  })
}
shinyApp(ui, server)

由于this 帖子中的建议,我尝试不使用observeEvent。这是服务器功能:

server <- function(input, output) {
  # 1
  output$plot <- renderPlot({
    input$action_input_1
    plot(rnorm(100))
    print(cat(paste0("mem used 1: ", capture.output(print(mem_used())),"\n")))
  })

  # 2
  output$plot <- renderPlot({
    input$action_input_2
    plot(rnorm(1000))
    print(cat(paste0("mem used 2: ", capture.output(print(mem_used())),"\n")))
  })
}

这里的内存没有增加,但只有第二个操作按钮(=最后一个代码块?)在工作。是否有防止内存泄漏并使两个按钮都工作的解决方案?

【问题讨论】:

    标签: r memory memory-leaks shiny observers


    【解决方案1】:

    如何使用 reactiveVal :

    reactiveData <- reactiveVal(NULL)
    observeEvent(input$action_input_1, reactiveData(rnorm(100)))
    observeEvent(input$action_input_2, reactiveData(rnorm(1000)))
    output$plot <- renderPlot(plot(reactiveData()))
    

    响应式值的语法略有不同:

    reactiveData <- reactiveValues(rnorm = NULL, bool_val = NULL) 
    
    observeEvent(input$action_input_1,  {# reactiveData(rnorm(100), bool_val <- TRUE)) 
       reactiveData$rnorm <- rnorm(100)
       reactiveData$bool_val <- TRUE
    })
    
    observeEvent(input$action_input_2, { #reactiveData(rnorm(1000), bool_val <- FALSE)) 
      reactiveData$rnorm <- rnorm(1000)
      reactiveData$bool_val <-  FALSE
    })
    
    output$plot <- renderPlot(plot(reactiveData$rnorm))
    

    虽然您的变量会同时发生变化,但从技术上讲,您仍然可以使用reactiveVal

    reactiveData <- reactiveVal(list(rnorm = NULL, bool_val = NULL)) 
    
    observeEvent(input$action_input_1, reactiveData(list(rnorm = 100, bool_val = TRUE)))
    
    observeEvent(input$action_input_2, reactiveData(list(rnorm = 1000, bool_val = FALSE)))
    
    output$plot <- renderPlot(plot(reactiveData()$rnorm))
    

    【讨论】:

    • 请注意,这使用了observeEvent,但没有嵌套renderPlot,我认为这是导致内存泄漏的原因。
    • 谢谢,这适用于示例,但不适用于我的用例。实际上,我想在第一个实例中将多个参数传递给 reactiveData。我想我必须使用 reactiveValues ,但它不起作用。你能检查一下这个代码吗:reactiveData &lt;- reactiveValues(rnorm = NULL, bool_val = NULL) observeEvent(input$action_input_1, reactiveData(rnorm(100), bool_val &lt;- TRUE)) observeEvent(input$action_input_2, reactiveData(rnorm(1000), bool_val &lt;- FALSE)) output$plot &lt;- renderPlot(plot(reactiveData()))
    • 你已经接近了。更新了我上面的答案。
    • 很好,它正在工作。你已经回答了我的问题。但是我遇到了另一个问题:如果我使用 'observe' 而不是 'observeEvent'(因为 reactiveData 会自动从文件更新),我在渲染新绘图时仍然会增加内存。
    • 我也试过rm(list = ls())gc(reset = TRUE)gc(),但似乎没有效果。
    猜你喜欢
    • 1970-01-01
    • 2016-02-13
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多