---
title: "Benchmarkme"
runtime: shiny
output:
  flexdashboard::flex_dashboard:
    css: style.css
    favicon: favicon.png
---
```{r include=FALSE, eval=FALSE}
drat::addRepo("csgillespie")
rsconnect::deployApp(
  appDir = "~/github/benchmarkme-data/inst/shinyapps_io/",
  account = "jumpingrivers",
  server = "shinyapps.io",
  appTitle = "benchmarkme"
)
```

```{r setup, include=FALSE}
library("shiny")
library("flexdashboard")
library("benchmarkmeData")
library("plotly")
data("past_results_v2", package = "benchmarkmeData")
source("functions.R")
```

Selections {.sidebar}
===============================

Select the machines you are interested in

```{r}
## The shiny part
selectInput("byte", "Byte compiled", c("All", "Standard", "Optimised"))
selectInput("blas", "Blas", c("All", "Standard", "Optimised"))
selectInput(
  "os",
  "Operating system",
  c("All", "Linux", "Apple", "Windows", "Unix")
)

checkboxInput("is_parallel", "Parallel benchmarks", TRUE)

selectInput(
  "test",
  "Benchmark test",
  c(
    "Programming",
    "Matrix functions",
    "Matrix calulations",
    "Read 5MB",
    "Read 50MB",
    "Read 200MB",
    "Write 5MB",
    "Write 50MB",
    "Write 200MB"
  )
)

fileInput("results", "Upload results file")

user_rank = NULL
results = reactive({
  if (!is.null(input$results)) {
    user_data = readRDS(file = input$results$datapath)
    user_results = summarise_results(user_data)
    all_results = rbind(past_results, user_results)
    user_id = unique(user_data$id)
  } else {
    all_results = past_results
    user_id = NULL
  }
  #res = select_results("prog", all_results)
  res = select_results("prog", all_results, parallel = TRUE)
  blas = get_option(input$blas)
  byte = get_option(input$byte)
  is_parallel = input$is_parallel
  res = select_results(
    get_test(input$test),
    all_results,
    byte_optimize = byte,
    blas_optimize = blas,
    parallel = is_parallel
  )
  res$is_user = FALSE
  res$is_user[res$id == user_id] = TRUE
  res = clean_table(res)

  if (input$os != "All") {
    res = res[res$sysname == input$os, ]
  }
  colnames(res) = c(
    "id",
    "Rank",
    "Time",
    "CPU",
    "Byte Compile",
    "BLAS Opt",
    "OS",
    "RAM (GB)",
    "Test",
    "Cores",
    "is_user"
  )

  res = res[, c(
    TRUE,
    !is_parallel,
    TRUE,
    TRUE,
    is.null(byte),
    is.null(blas),
    input$os == "All",
    TRUE,
    input$Test == "All",
    TRUE,
    is_parallel,
    TRUE
  )]
  if (nrow(res) > 0) {
    res$Rank = seq_len(nrow(res))
  }
  res
})
br()

renderUI({
  ret = NULL
  user_rank = which(results()$is_user)

  if (!is.null(input$results)) {
    ret = paste(ret, "File uploaded.", br(), br())

    if (sum(user_rank) > 0) {
      ret = paste(
        ret,
        "Your machine is ranked",
        user_rank,
        "out of",
        nrow(results()),
        "machines"
      )
    } else {
      ret = paste(
        ret,
        br(),
        "For the current selection, your own
                machine isn't displayed"
      )
    }
  }
  HTML(ret)
})

div(
  class = "div-wrapper",
  a(
    href = "http://www.jumpingrivers.com",
    img(src = "logo.png", style = "width:150px;")
  )
)
```


Table
=====================================

### Top machines

```{r}
DT::renderDataTable({
  r = results()
  data_table = DT::datatable(results()[, -c(1, ncol(r))], rownames = FALSE)
  if (sum(r$is_user) > 0) {
    DT::formatStyle(
      data_table,
      "Rank",
      backgroundColor = DT::styleEqual(which(r$is_user), "orange")
    )
  } else {
    data_table
  }
})
```

Graphics
=====================================

### Absolute time

```{r}
library(plotly)
renderPlotly({
  res = results()
  if (nrow(res) > 0) {
    res$size = res$is_user + 6
    res$size[res$is_user] = 16
    res$colour = "black"
    res$colour[res$is_user] = "steelblue"
    if (!input$is_parallel) {
      plot_ly(
        res,
        x = ~Rank,
        y = ~`Time`,
        type = "scatter",
        marker = list(color = ~colour, width = 10, size = ~size),
        #          color= ~is_user, size=~size,
        text = ~ paste("CPU: ", CPU)
      ) |>
        layout(yaxis = list(type = "log", title = "Time (sec)"))
    } else {
      saveRDS(res, file = "/tmp/tmp.rds")
      plot_ly(
        res,
        x = ~Cores,
        y = ~`Time`,
        type = "scatter",
        marker = list(color = ~colour, width = 10, size = ~size),
        #          color= ~is_user, size=~size,
        text = ~ paste("CPU: ", CPU)
      ) |>
        add_lines(color = ~id) |>
        layout(
          yaxis = list(type = "log", title = "Normalised time (to 1 core)"),
          showlegend = FALSE
        )
    }
  } else {
    plot_ly()
  }
})
```

### Relative time

```{r}
library(plotly)
renderPlotly({
  if (!input$is_parallel && nrow(results()) > 0) {
    relative = (results()$Time / min(results()$Time))
    plot_ly(
      results(),
      x = ~Rank,
      y = ~relative,
      text = ~ paste("CPU: ", CPU)
    ) |>
      layout(yaxis = list(type = "log", title = "Relative time"))
  } else {
    plot_ly()
  }
})
```

Machine summary
=====================================

Column 1
------------------------------------

### CPUs

```{r}
total = function(i) sum(i > 0, na.rm = TRUE)
renderPlotly({
  i3 = total(regexpr("i3", results()$CPU))
  i5 = total(regexpr("i5", results()$CPU))
  i7 = total(regexpr("i7", results()$CPU))
  xeon = total(regexpr("Xeon", results()$CPU))
  amd = total(regexpr("AMD", results()$CPU))
  plot_ly(
    x = c(paste("Intel", c("i3", "i5", "i7", "Xeon")), "AMD"),
    y = c(i3, i5, i7, xeon, amd),
    name = "CPU distribution",
    type = "bar"
  )
})
```

### RAM

```{r}

renderPlotly({
  ram = table(results()$`RAM (GB)`)
  n = as.numeric(as.character(names(ram)))
  x_axis = factor(n)
  plot_ly(
    x = x_axis,
    y = ram,
    name = "CPU distribution",
    type = "bar"
  )
})
```

<!-- Column 2 -->
<!-- ------------------------------------ -->

### Operating system

```{r}
total = function(i) sum(i > 0, na.rm = TRUE)
renderPlotly({
  OS = sort(table(results()$OS))
  nam = as.character(names(OS))

  plot_ly(
    x = nam,
    y = as.vector(OS),
    name = "OS distribution",
    type = "bar"
  )
})
```


Benchmark description
=====================================

### Overview

There are two main benchmarks in this package:

  * `benchmark_std()`
    - This consists of three sub benchmarks: `benchmark_prog`,
    `benchmark_matrix_cal`, and `benchmark_matrix_fun`
  * `benchmark_io()`
    - This consists of two sub benchmarks: `read` and `write`.

#### Programming benchmarks

The `benchmark_prog` benchmark consists of timing five matrix programming operations:

  * $3,500,000$ Fibonacci numbers calculation (vector calc) - `bm_prog_fib`.
  * Creation of a $3500 \times 3500$ Hilbert matrix (matrix calc) - `bm_prog_hilbert`.
  * Grand common divisors of $1,000,000$ pairs (recursion) - `bm_prog_gcd`.
  * Creation of a $1600\times 1600$ Toeplitz matrix (loops) - `bm_prog_toeplitz`.
  * Escoufier's method on a $60\times 60$ matrix (mixed) - `bm_prog_escoufier`.

#### Matrix calulations

A collection of matrix benchmark functions aimed at assessing the calculation speed.

  * Creation, transp., deformation of a $2500\times 2500$ matrix - `bm_matrix_cal_manip`.
  * $2500\times2500$ normal distributed random matrix ^1000 - `bm_matrix_cal_power`.
  * Sorting of $7,000,000$ random values - `bm_matrix_cal_sort`.
  * $2500\times 2500$ cross-product matrix ($b = a' \times a$) - `bm_matrix_cal_cross_product`
  * Linear regression over a $3000 \times 3000$ matrix - `bm_matrix_cal`.

#### Matrix functions

A collection of matrix benchmark functions

  * FFT over $2,500,000$ random values - `bm_matrix_fun_fft`.
  * Eigenvalues of a $640\times 640$ random matrix - `bm_matrix_fun_eigen`.
  * Determinant of a $2500 \times 2500$ random matrix - `bm_matrix_fun_determinant`.
  * Cholesky decomposition of a $3000 \times 3000$ matrix - `bm_matrix_fun_cholesky`.
  * Inverse of a $1600 \times 1600$ random matrix - `bm_matrix_fun_inverse`.

#### Input/Output

  * Reading a $5$, $50$ and $200$MB csv file
  * Writing a $5$, $50$ and $200$MB csv file

The purpose of this benchmark isn't to compare `write.csv` to another package. Instead,
we went to assess your machine.


---

These benchmarks have been developed by many [authors](http://r.research.att.com/benchmarks/R-benchmark-25.R).
