I have a general question about shiny reactive functions with some pseudo code to demonstrate essentially what I am trying to do. I essentially am wondering why even though each of my reactive functions are very quick, but when I am running the shiny app, there seems to be a significant delay between each of the functions. Thus, what seems to be making the app slow is not my individual functions but rather whatever is happening in between my reactive functions. This is pseudo code for what I am trying to do with some comments. If you need a complete reproducible example, it may take me awhile to create one, but I will eventually finish it. As for now, I am trying to just explain my thought process and see if this is some higher-level conceptual thing about reactive functions that I should take a look at to solve my speed issue.
## Global variables: long_list, initial_df
shinyApp(ui = fluidPage(
titlePanel("Example"),
sideBarLayout(
sideBarPanel(
## long_list is a variable that contains all of the possible choices.
## There are many choices.
selectInput("symbols",
"Possible Choices",
long_list)
## Have a few conditional panels. These
## contain date range sliders and tables.
conditionalPanel(
tableOutput("table1")
tableOutput("table2")
.
.
.
tableOutput("table10")
),
conditionalPanel(
tableOutput("table11")
)
...),
mainPanel(
## many plots being rendered
rCharts::showOutput("plot1", "nvd3"),
rCharts::showOutput("plot2", "nvd3"),
.
.
.
rCharts::showOutput("plot10", "nvd3"),
conditionalPanel(
## some condition
rCharts::showOutput("plot11", "nvd3")
)
...)
)
),
server = function(input, output) {
## returns a data frame that reacts to a change in some input,
## such as a radio button or a slider, and then returns a
## dataframe that my plotting functions will use. It filters
## a global data frame by a certain symbol in this pseudo example.
## This makes the data frame of interest smaller and thus results
## in different plots depending on which symbol the user chooses.
filtered_data_frame <- reactive({
## df is a global variable that contains a pre-calculated data frame.
if(!is.null(input$symbols)) {
return(dplyr::filter(df, symbol == input$symbols))
}
## if the initial check does not pass (we have a null symbol)
## then we return NULL. This is for validation in the
## plotting functions to do nothing if this function returns
## NULL
return(NULL)
})
output$plot1 <- rCharts::renderChart2({
## checks to make sure the function above returns a non-null
## result before proceeding. Otherwise does nothing (empty string "")
validate(
need(!is.null(filtered_data_frame()), "")
)
## nvd3 plot using rCharts
g <- nPlot(...)
g
})
output$plot2 <- rCharts::renderChart2({
validate(
need(!is.null(filtered_data_frame()), "")
)
g <- nPlot(...)
g
})
## This continues for say 11 plots, (i.e. output$plot3...output$plot11)
## and similarly the for say 11 tables, (i.e output$table1...output$table11)
## The tables render data frames.
}
)
Now each of the reactive functions, (i.e. filtered_data_frame(), output$plot1, output$table1...output$plot11, output$table11) are all individually very quick. I put a print statement for the start of each function and the end of each of function and they almost pretty instantaneously one after the other. For example:
output$plot1 <- rCharts::renderChart2({
validate(...)
print("start")
...
g <- nPlot(...)
...
print("end")
## g is the name of the plot I return
g
})
I have these "start" and "end" print statements for each of my reactive functions, and each individual function runs very quickly, but there are pauses between one function's "end" and another function's "start" that I cannot explain. I am not too sure what is causing these long pauses. I spent a lot of time optimizing each of my functions only to find out that most of the time did not seem to be within the functions but perhaps something slow with the reactive nature of shiny. Is there a way to reduce the long pauses between reactive functions in shiny? If more information is needed, I can provide a full reproducible example, but again it would probably take awhile to make an application that has as long of pauses as mine does.
I did notice that when I used a larger dataset as input (a larger dataset for the initial_df global variable), my app did run slower, but again not so much within each of the functions but rather long pauses between functions. Does anyone have any insight into this issue? Any help is greatly appreciated! Thank you!