代码之家  ›  专栏  ›  技术社区  ›  JHall651

如何在r中的闪亮应用程序中计时反应函数

  •  2
  • JHall651  · 技术社区  · 7 年前

    我有一个我想计时的函数,然后在UI上显示执行该函数所需的时间。如何重新获得该函数的执行时间?我试着把变量放在反应函数中,围绕函数等等。我只是想计算反应函数运行所需的时间,然后显示它。我尽量不使用其他软件包。

    library(shiny)
    # Define UI for application that draws a histogram
    ui <- fluidPage(
    
      sidebarPanel(
        # User Input Text  Box
        textInput(inputId = "userText",
              label = "",
              placeholder = "Type in a partial sentence here..."),
        verbatimTextOutput(outputId = "textInput", placeholder = TRUE),
    
        # Show amount of execution time
        verbatimTextOutput(outputId = "timer", placeholder = TRUE)  
    ))
    
    server <- function(input, output) {
    
      # Declare Timer variables
      startTime <- Sys.time()
      endTime <- Sys.time()
    
      # Some function to time: Trivial Paste Function
      textToDisplay <- reactive({
        req(input$userText)
        startTime <- Sys.time()
        textToDisplay <- paste("This is the user input text: ", input$userText)
        endTime <- Sys.time()
        return(textToDisplay)
      })
    
      # Display pasted text
      output$textInput <- renderText({
        req(input$userText)
        textToDisplay()
    
      })
    
      # Display execution time
      output$timer <- renderText({
        req(input$userText)
        paste0("Executed in: ",((endTime - startTime)*1000)," milliseconds")
      })
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    

    上述代码不能正确更新或显示正确的时差。

    3 回复  |  直到 7 年前
        1
  •  4
  •   divibisan    7 年前

    啊,问题是 startTime endTime 不是反应性值,所以当它们改变时不会导致 renderText 使其无效并重新运行,并且它们在反应式表达式之外不能正确持久。

    只需定义 reactiveValues 对象,并生成 开始时间 结束时间 部分原因。

    将定义计时器变量的部分替换为:

    rv <- reactiveValues()
    

    然后,每次你拜访 开始时间 结束时间 使用 rv$startTime rv$endTime

    你仍然看不到结果,因为 textToDisplay 运行太快,但如果您进行了这些更改并添加 Sys.sleep(2) 进入 文本显示 你会发现它工作正常。

        2
  •  3
  •   r2evans    7 年前

    我认为那里有一些不必要的代码。您对的定义 startTime endTime 两者都在 server 个别反应性语块令人困惑(对你和读者都是如此);当然,这两个位置都不是必需的,因为我更喜欢使用 system.time ,我建议两个位置都不需要。

    有两种方法可以处理从块中获取两个返回值(数据和经过的时间):(1)返回 list ,和(2) reactiveValues()

    保持您的 ui shinyApp 。。。

    对于第一个选项( 列表 ),这个 服务器 组件变成:

    server <- function(input, output) {
      mydat <- eventReactive(input$userText, {
        req(input$userText)
        tm <- system.time({
          Sys.sleep(runif(1))
          out <- paste("This is the user input text:", sQuote(input$userText))
        })
        list(x=out, elapsed=tm['elapsed'])
      })
      # Display pasted text
      output$textInput <- renderText({
        req(mydat())
        mydat()$x
      })
      # Display execution time
      output$timer <- renderText({
        req(mydat())
        paste0("Executed in: ", round(mydat()$elapsed*1000), " milliseconds")
      })
    }
    

    对于第二个选项,请尝试:

    server <- function(input, output) {
      times <- reactiveVal()
      mydat <- reactiveVal()
      # operates in side-effect
      observeEvent(input$userText, {
        req(input$userText)
        tm <- system.time({
          Sys.sleep(runif(1))
          out <- paste("This is the user input text:", sQuote(input$userText))
        })
        times(tm['elapsed'])
        mydat(out)
      })
      # Display pasted text
      output$textInput <- renderText({
        req(mydat())
        mydat()
      })
      # Display execution time
      output$timer <- renderText({
        req(times())
        paste0("Executed in: ", round(times()*1000), " milliseconds")
      })
    }
    

    (而不是两个 reactiveVal() 变量,也可以使用@divibisan的建议 反应值() ,相同的最终结果。)

        3
  •  0
  •   JHall651    7 年前

    我使用了一种结合了您的建议@r2evans和@divibisan的方法。我使用了reactiveValues,因为我认为它是用户可读的,并且可以很容易地扩展到其他用途。我使用了这个系统。建议的时间。当函数运行时,它会更新反应值,返回语句控制从函数返回适当的值。

    server <- function(input, output) {
      options(digits.secs=2)
    
      # Declare Timer variables
      rv <- reactiveValues(
        exTime = Sys.time()
      )
    
      # Trivial Paste Function
      textToDisplay <- reactive({
        req(input$userText)
        t <- system.time({
          textToDisplay <- paste("This is the user input text: ", 
                                 input$userText)
          })
        rv$exTime <- t[[3]]
        return(textToDisplay)
      })
    
      # Display pasted text
      output$textInput <- renderText({
        req(input$userText)
        textToDisplay()
      })
    
      # Display execution time
      output$timer <- renderText({
        req(input$userText)
        paste0("Executed in: ",((rv$exTime)*1000)," milliseconds")
      })
    }
    

    正如@divibisan所建议的那样,这将显示0,因为代码运行速度很快。您可以增加从 system.time() 具有 options(digits.secs=2) ,我将其添加到服务器代码的顶部。对于实际函数,这给了我在Windows中运行10毫秒的精度。