source(here::here("posts", "_helpers.R"))
post_path <- "posts/2026-10-07-call-overhead-i547"
file_link <- file_linker(post_path)
section_link <- section_linker(post_path)
# the models' sections of benchmark.R, shown below by their labels
knitr::read_chunk(here(post_path, "benchmark.R"))
sessions <- read_sessions(post_path)
n_sessions <- length(sessions)
# the second run, of mcmc() with verbose = FALSE alone
sessions_one_call <- read_sessions(post_path, "results-one-call")
one_call_settings <- sessions_one_call[[1]]$results[[1]]$one_call_settings
# the third run, of #855 as measured here and as it stands after the PR's
# review
sessions_review <- read_sessions(post_path, "results-review-head")
review_labels <- c(measured = "#855", reviewed = "#855 reviewed")
review_versions <- display_versions(
sessions_review[[1]]$versions,
labels = review_labels
)
# the names the results give the versions, and the names this page shows
version_labels <- c(CRAN = "CRAN", earlier = "#855 before", branch = "#855")
# pak installed earlier and branch from archives of their commits, which the
# results record as local paths; run.R names the same commits on GitHub
versions <- display_versions(
sessions[[1]]$versions,
labels = version_labels,
on_github = c(
earlier = "greta-dev/greta@11405935549722ecbf035a2712a007419e52af66",
branch = "greta-dev/greta@f30ab1469ef9eafab8bb2ff48be10860cd3fd9ab"
)
)
version_levels <- names(versions)
colours <- version_colours(version_levels)
bench_settings <- sessions[[1]]$results[[1]]$bench_settings
# how the text names each version: #855 links to the PR, and #855 before to
# its commit
version_text <- c(
CRAN = "CRAN",
`#855 before` = paste0(
"[#855 before](",
commit_url(versions[["#855 before"]]),
")"
),
`#855` = paste0("[#855](", pr_url(855), ")")
)
version_ref <- function(version) I(version_text[[version]])
# one row per session and version, holding that version's results, with the
# versions named and ordered by `labels`
runs_of <- function(session_files, labels) {
lapply(session_files, function(session_file) {
tibble(
session = session_file$session,
version = factor(
unname(labels[names(session_file$results)]),
levels = unname(labels)
),
results = unname(session_file$results)
)
}) |>
bind_rows()
}
runs <- runs_of(sessions, version_labels)
model_levels <- names(runs$results[[1]]$mcmc)
# opt() was also timed at fewer iterations, which this page leaves out
opt_iterations <- max(bench_settings$opt_max_iterations)
# what each figure has a row of panels for: mcmc()'s three ways of running,
# named as benchmark.R names them, and opt()
case_labels <- c(
one_by_one = "mcmc(), one_by_one = TRUE, no progress bar",
progress = "mcmc(), progress bar shown (verbose = TRUE)",
one_call = "mcmc(), no progress bar (verbose = FALSE)",
opt = paste0("opt(), adam(), max_iterations = ", opt_iterations)
)
mcmc_cases <- c("one_by_one", "progress", "one_call")
# every timed call in `runs`, in every session, version, model and case
timed_calls_of <- function(runs) {
lapply(seq_len(nrow(runs)), function(i) {
lapply(model_levels, function(model_name) {
mcmc_marks <- runs$results[[i]]$mcmc[[model_name]]
mcmc_calls <- lapply(mcmc_cases, function(mode) {
every_call(mcmc_marks[[mode]]) |> mutate(case = case_labels[[mode]])
})
opt_calls <- every_call(
runs$results[[i]]$opt[[model_name]],
max_iterations
) |>
filter(max_iterations == opt_iterations) |>
select(-max_iterations) |>
mutate(case = case_labels[["opt"]])
bind_rows(mcmc_calls, opt_calls) |>
mutate(model = model_name)
}) |>
bind_rows() |>
mutate(session = runs$session[i], version = runs$version[i])
}) |>
bind_rows() |>
mutate(
model = factor(model, levels = model_levels),
case = factor(case, levels = case_labels)
)
}
timed_calls <- timed_calls_of(runs)
# each version's median first call, and median call after the first, for each
# case and model, and how many times as long #855 before and CRAN take as #855
call_medians <- timed_calls |>
group_by(calls, case, model, version) |>
summarise(seconds = median(seconds), .groups = "drop") |>
pivot_wider(names_from = version, values_from = seconds) |>
mutate(
before_over_pr = `#855 before` / `#855`,
cran_over_pr = CRAN / `#855`
)
# one column of call_medians, over the two models and the cases named
ratios_of <- function(column, cases, which_calls = "calls after the first") {
rows <- call_medians$calls == which_calls &
call_medians$case %in% case_labels[cases]
call_medians[[column]][rows]
}
range_of <- function(column, cases, which_calls = "calls after the first") {
format_range(ratios_of(column, cases, which_calls))
}
# how #855 before and CRAN compare with #855, naming the slower
before_vs_pr <- function(cases, which_calls = "calls after the first") {
compare_times(
ratios_of("before_over_pr", cases, which_calls),
version_text[["#855 before"]],
version_text[["#855"]]
)
}
cran_vs_pr <- function(cases, which_calls = "calls after the first") {
compare_times(
ratios_of("cran_over_pr", cases, which_calls),
version_text[["CRAN"]],
version_text[["#855"]]
)
}
# the sections of benchmark.R a reader runs to repeat the main run, in order
main_run_sections <- c(
"benchmark-setup",
"benchmark-settings",
"model-linear",
"model-hierarchical-linear",
"benchmark-mcmc",
"benchmark-opt",
"bench-linear",
"bench-hierarchical-linear"
)
main_run_returns <- paste(
"list(mcmc = list(linear = linear_mcmc,",
"hierarchical_linear = hierarchical_linear_mcmc),",
"opt = list(linear = linear_opt, hierarchical_linear = hierarchical_linear_opt))"
)
# what each "Run it yourself" block shows: the main run, and the second run
# of mcmc() with verbose = FALSE, on #855 before and #855 only
main_run_code <- run_it_yourself(
post_path,
"benchmark.R",
main_run_sections,
versions,
main_run_returns
)
one_call_code <- run_it_yourself(
post_path,
"benchmark-one-call.R",
c("one-call-setup", "one-call-settings", "one-call-models", "one-call-mcmc"),
versions[c("#855 before", "#855")],
"list(linear = linear_one_call, hierarchical_linear = hierarchical_linear_one_call)"
)