## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = as.logical(Sys.getenv("CPP11_EVAL", "false"))
)

print_cpp <- function(filename) {
  cat("```c++", readLines(filename), "```", sep = "\n")
}

library(cpp11)

should_run_benchmarks <- function(x) {
  get("requireNamespace")("cpp11test", quietly = TRUE) && asNamespace("cpp11test")$should_run_benchmarks()
}

## -----------------------------------------------------------------------------
x <- c(1, 2, 3)
y <- x

## -----------------------------------------------------------------------------
y[[3]] <- 4
y

x

## -----------------------------------------------------------------------------
x <- c(1, 2, 3)
y <- x * 2
y

x

## -----------------------------------------------------------------------------
z <- times_two_rcpp(x)
z

x

## -----------------------------------------------------------------------------
x <- c(1, 2, 3)

z <- times_two_cpp11(x)
z

x

## ----R.options = list(max.print = 20)-----------------------------------------
1:1e9

## -----------------------------------------------------------------------------
x <- identity_rcpp(1:100000)
lobstr::obj_size(x)

## -----------------------------------------------------------------------------
y <- identity_cpp11(1:100000)
lobstr::obj_size(y)

## ----message = FALSE, results = 'asis', eval = should_run_benchmarks()--------
# library(cpp11test)
# 
# cases <- expand.grid(
#   len = 3e6,
#   vector = c("normal", "altrep"),
#   method = c("for", "foreach", "accumulate"),
#   pkg = c("cpp11", "rcpp"),
#   stringsAsFactors = FALSE
# )
# 
# # Add special case
# cases <- rbind(list(len = 3e6, vector = "normal", method = "for2", pkg = "cpp11"), cases)
# 
# b_sum <- bench::press(
#   .grid = cases,
#   {
#     seq_real <- function(x) as.numeric(seq_len(x))
#     funs <- c("normal" = rnorm, "altrep" = seq_real)
#     x <- funs[[vector]](len)
#     fun <- match.fun(sprintf("%ssum_dbl_%s_", ifelse(pkg == "cpp11", "", paste0(pkg, "_")), method))
#     bench::mark(
#       fun(x)
#     )
#   }
# )[c("pkg", "method", "vector", "min", "median", "mem_alloc", "itr/sec", "n_gc")]
# 
# saveRDS(b_sum, "sum.Rds", version = 2)

## -----------------------------------------------------------------------------
knitr::kable(readRDS("sum.Rds"))

## ----eval = FALSE, include = FALSE--------------------------------------------
# # count lines for Rcpp headers (excluding comments)
# # brew install cloc
# git clone https://github.com/RcppCore/Rcpp
# cd Rcpp
# git checkout 1.0.4
# cloc inst/include
# 
# # count lines for Rcpp headers without generated code
# cloc --fullpath --not-match-f '.*generated.*' inst/include
# 
# # count lines for cpp11 headers
# git clone https://github.com/r-lib/cpp11
# cd cpp11
# cloc inst/include
# 
# # get primary authors of Rcpp
# git ls-files -- inst/include | while read f; do git blame -w --line-porcelain -- "$f" | grep -I '^author '; done | sort -f | uniq -ic | sort -nr

## ----eval = FALSE, include = FALSE--------------------------------------------
# # brew install gtime
# # CC=gcc-9 CXX=g++-9 CXX11=g++-9
# gtime -f %M:%e R CMD INSTALL --libs-only --use-vanilla .

## ----message = FALSE, eval = should_run_benchmarks()--------------------------
# library(cpp11test)
# grid <- expand.grid(len = c(10 ^ (2:5), 2e5), pkg = c("cpp11", "rcpp"), stringsAsFactors = FALSE)
# b_release <- bench::press(.grid = grid,
#   {
#     fun = match.fun(sprintf("%s_release_", pkg))
#     bench::mark(
#       fun(len),
#       iterations = 1
#     )
#   }
# )[c("len", "pkg", "min")]
# saveRDS(b_release, "release.Rds", version = 2)

## ----echo = FALSE, dev = "svg", fig.ext = "svg", eval = capabilities("cairo")----
b_release <- readRDS("release.Rds")
library(ggplot2)
ggplot(b_release, aes(x = len, y = min / len, color = pkg)) +
  geom_point() +
  geom_line() +
  bench::scale_y_bench_time(base = NULL) +
  scale_x_continuous(labels = scales::comma)+
  labs(
    tite = "cpp11 uses constant time protection",
    x = "Number of protected objects",
    y = "Average time to release protection on one object"
  )

## ----echo = FALSE-------------------------------------------------------------
knitr::kable(b_release)

## ----message = FALSE, eval = should_run_benchmarks()--------------------------
# grid <- expand.grid(len = 10 ^ (0:7), pkg = "cpp11", stringsAsFactors = FALSE)
# grid <- rbind(
#   grid,
#   expand.grid(len = 10 ^ (0:4), pkg = "rcpp", stringsAsFactors = FALSE)
# )
# b_grow <- bench::press(.grid = grid,
#   {
#     fun = match.fun(sprintf("%sgrow_", ifelse(pkg == "cpp11", "", paste0(pkg, "_"))))
#     bench::mark(
#       fun(len),
#       min_iterations = 100
#     )
#   }
# )[c("len", "pkg", "min", "mem_alloc", "n_itr", "n_gc")]
# saveRDS(b_grow, "growth.Rds", version = 2)

## ----echo = FALSE, dev = "svg", fig.ext = "svg", eval = capabilities("cairo")----
b_grow <- readRDS("growth.Rds")
library(ggplot2)
ggplot(b_grow, aes(x = len, y = min, color = pkg)) +
  geom_point() +
  geom_line() +
  bench::scale_y_bench_time() +
  scale_x_log10(
    breaks = scales::trans_breaks("log10", function(x) 10^x),
    labels = scales::trans_format("log10", scales::math_format(10^.x))
  ) +
  coord_fixed() +
  theme(panel.grid.minor = element_blank()) +
  labs(title = "log-log plot of vector size vs construction time", x = NULL, y = NULL)

## ----echo = FALSE-------------------------------------------------------------
knitr::kable(b_grow)

