Optimizing Performance with Tabs and suspendWhenHidden = FALSE

Hello,

I've got a Flexdashboard-based Shiny application with several tabs, and within each tab, grids of multiple plots. Performance is a bit of an issue, particularly when deployed on the free Shiny Server.

Initially, the main issue was that clicking each tab would require re-rendering of the plots. I set the suspendWhenHidden option to be FALSE, and this helps - Now switching the input has a slow delay to load all the plots, but at least when navigating the UI, performance is snappy.

This got me thinking, however - is there any way to achieve a hybrid of the two behaviors? So say I'm on an active tab which just produces a single plot. This plot renders quickly. Can we tell shiny to render this plot, display it to the user, and then in the background, continue loading all the elements of the other tabs? As it stands now, the active tab will not finish rendering the plot until all plots on the hidden tabs are also rendered.

In summary, a hybrid suspendWhenHidden = FALSE and TRUE:

  1. Render the active tab elements first, display to the user, then
  2. Continue rendering the elements on the hidden tabs

I thought perhaps setting priority might achieve this, but it doesn't seem to work. Any thoughts or suggestions?

EDIT: Here's a minimal reproducible example. The goal would be for the first plot (in tab 1) to render and appear before beginning rendering of the second plot (in tab 2) - But the plot should start rendering in tab 2 without requiring a click of tab 2.

library(shiny)

ui <- fluidPage(
    sidebarLayout(
        sidebarPanel(
            numericInput('n', 'Size', 10)
        ),
        mainPanel(
            tabsetPanel(
                tabPanel("Tab1", plotOutput("plot1")),
                tabPanel("Tab2", plotOutput("plot2"))))
    )
)

# Define the server code
server <- shinyServer(function(input, output, session) {
    output$plot1 <- renderPlot({plot(1:input$n)},height = 400,width=800)
    output$plot2 <- renderPlot({ Sys.sleep(5); plot(1:input$n,col="red")},height = 400,width=800)
    outputOptions(output, "plot2", suspendWhenHidden = FALSE)
})

# Return a Shiny app object
shinyApp(ui = ui, server = server)
2 Likes