Speed concerns, renderHighchart() vs renderUI()

My intuition is that renderUI() is slower because you're essentially creating a complete, new HTML widget for each highchart() in the renderUI().

renderHighchart() can load the highchart dependencies and setup the htmlwidget infrastructure one time and then use this infrastructure for every htmlwidget created through renderHighchart().

But inside renderUI() the HTML could be anything, so htmlwidgets has to resolve and check if it should load the highcharts dependencies for each element (or at least once per render).

Here's an only slightly janky solution that uses renderUI() to create the highchartOutput()s and a for loop to call renderHighchart(). Profiling this example shows that, other than the static renderUI() cost, the "dynamic" highcharts in the for loop are just as fast as the single renderHighchart().

library(shiny)
library(highcharter)

options(shiny.launch.browser = TRUE)

samp <- sample(5000, 100, replace = TRUE)

ui <- fluidPage(
  actionButton("update", "Update"),
  sliderInput("n_charts", "Number of Charts", min = 1, max = 5, value = 2),
  fluidRow(
    column(
      width = 6,
      h5("Highcharter output"),
      highchartOutput("hc_chart")
    ),
    column(
      width = 6,
      h5("Manually Dynamic"),
      uiOutput("hc_dynamic")
    )
  )
)

server <- function(input, output) {
  output$hc_chart <- renderHighchart({
    input$update
    highchart() %>%
      hc_chart(type = "column") %>%
      hc_title(text = "renderHighchart()") %>%
      hc_xAxis(categories = seq_along(samp)) %>%
      hc_add_series(
        data = samp,
        name = "Downloads"
      )
  })
  
  output$hc_dynamic <- renderUI(
    tagList(
      lapply(seq_len(input$n_charts), function(n) highchartOutput(paste0("chart_", n)))
    )
  )
  
  observeEvent(input$update, {
    for (n in seq_len(input$n_charts)) {
      output[[paste0("chart_", n)]] <- renderHighchart({
        highchart() %>%
          hc_chart(type = "column") %>%
          hc_title(text = "renderHighchart()") %>%
          hc_xAxis(categories = seq_along(samp)) %>%
          hc_add_series(
            data = samp,
            name = "Downloads"
          )
      })
    }
  }, ignoreInit = FALSE, ignoreNULL = FALSE)
}

app <- shinyApp(ui = ui, server = server)
1 Like