From 6c5c76e54bb1759d018b7cb3232f3e9503e2fa78 Mon Sep 17 00:00:00 2001 From: CyGei Date: Sat, 27 Sep 2025 16:11:38 -0400 Subject: [PATCH 1/4] pipe_id fingerprint approach: identifies a unique expression form --- R/emit.R | 8 ++++++-- R/time_pipe.R | 17 ++++++++++++----- R/zzz.R | 6 ++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/R/emit.R b/R/emit.R index d61566e..b1bf55f 100644 --- a/R/emit.R +++ b/R/emit.R @@ -7,12 +7,14 @@ #' @param label Character. Operation label. #' @param unit Character. Time unit ("secs", "mins", "hours", "days", or "weeks"). #' @param console Logical. Print timing to the console? -#' @param log Character or NULL. Name of a data frame in `.pipetime_env` for logging. +#' @param log Character or NULL. Name of a data frame in .pipetime_env for logging. +#' @param pipe_id Numeric. The ID of the current pipeline. #' #' @return Invisibly, the numeric duration of the operation. #' @keywords internal #' @noRd -emit <- function(start, end, label, unit, console, log) { +emit <- function(start, end, label, unit, console, log, pipe_id) { + # Added pipe_id duration <- as.numeric(difftime(end, start, units = unit)) duration <- sprintf("%.4f", duration) timestamp <- format(start, "%Y-%m-%d %H:%M:%OS3") @@ -43,6 +45,7 @@ emit <- function(start, end, label, unit, console, log) { } new_row <- data.frame( + pipe_id = pipe_id, timestamp = timestamp, label = label, duration = as.numeric(duration), @@ -60,5 +63,6 @@ emit <- function(start, end, label, unit, console, log) { assign(log, new_row, envir = .pipetime_env) } } + invisible(duration) } diff --git a/R/time_pipe.R b/R/time_pipe.R index 6b898b5..aa1528d 100644 --- a/R/time_pipe.R +++ b/R/time_pipe.R @@ -32,10 +32,17 @@ time_pipe <- function( console = getOption("pipetime.console", TRUE), unit = getOption("pipetime.unit", "secs") ) { - unit <- match.arg( - unit, - choices = c("secs", "mins", "hours", "days", "weeks") - ) + # --- Pipeline fingerprint --- + call_hash <- digest::digest(sys.calls()[[1]]) + + if (!identical(.pipetime_env$last_hash, call_hash)) { + .pipetime_env$pipe_counter <- .pipetime_env$pipe_counter + 1L + .pipetime_env$last_hash <- call_hash + } + pipe_id <- .pipetime_env$pipe_counter + # ---------------------------- + + unit <- match.arg(unit, c("secs", "mins", "hours", "days", "weeks")) start <- Sys.time() result <- .data @@ -46,7 +53,7 @@ time_pipe <- function( label <- gsub("\\s+", "", paste(deparse(expr), collapse = "")) } - emit(start, end, label, unit, console, log) + emit(start, end, label, unit, console, log, pipe_id) result } diff --git a/R/zzz.R b/R/zzz.R index 4056707..a8be53a 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1 +1,7 @@ .pipetime_env <- new.env(parent = emptyenv()) + +# Global counter for pipeline IDs +.pipetime_env$pipe_counter <- 0L + +# Store last pipeline hash +.pipetime_env$last_hash <- NULL From 026d025e28aa68943fe19943c0d79e32c084525a Mon Sep 17 00:00:00 2001 From: CyGei Date: Sat, 27 Sep 2025 16:18:11 -0400 Subject: [PATCH 2/4] pipe_id to identify each execution run - globally --- R/time_pipe.R | 12 ++++++------ R/zzz.R | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/time_pipe.R b/R/time_pipe.R index aa1528d..c1da72f 100644 --- a/R/time_pipe.R +++ b/R/time_pipe.R @@ -32,15 +32,15 @@ time_pipe <- function( console = getOption("pipetime.console", TRUE), unit = getOption("pipetime.unit", "secs") ) { - # --- Pipeline fingerprint --- - call_hash <- digest::digest(sys.calls()[[1]]) - - if (!identical(.pipetime_env$last_hash, call_hash)) { + # --- New run detection --- + if (!.pipetime_env$active_run) { .pipetime_env$pipe_counter <- .pipetime_env$pipe_counter + 1L - .pipetime_env$last_hash <- call_hash + .pipetime_env$active_run <- TRUE + # Reset active_run at the end of the top-level evaluation + on.exit(.pipetime_env$active_run <- FALSE, add = TRUE) } pipe_id <- .pipetime_env$pipe_counter - # ---------------------------- + # -------------------------- unit <- match.arg(unit, c("secs", "mins", "hours", "days", "weeks")) diff --git a/R/zzz.R b/R/zzz.R index a8be53a..d838159 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -3,5 +3,5 @@ # Global counter for pipeline IDs .pipetime_env$pipe_counter <- 0L -# Store last pipeline hash -.pipetime_env$last_hash <- NULL +# Track whether we’re already inside a pipeline run +.pipetime_env$active_run <- FALSE From d8ee3501d6406ec8f54c83dba177e2a4651401b4 Mon Sep 17 00:00:00 2001 From: CyGei Date: Sat, 27 Sep 2025 17:10:15 -0400 Subject: [PATCH 3/4] pipe_id to identify each execution run - per log --- R/emit.R | 15 ++++++--------- R/rm_log.R | 2 ++ R/time_pipe.R | 35 ++++++++++++++++++++++++++--------- R/zzz.R | 8 ++++---- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/R/emit.R b/R/emit.R index b1bf55f..34dfc67 100644 --- a/R/emit.R +++ b/R/emit.R @@ -14,31 +14,28 @@ #' @keywords internal #' @noRd emit <- function(start, end, label, unit, console, log, pipe_id) { - # Added pipe_id duration <- as.numeric(difftime(end, start, units = unit)) - duration <- sprintf("%.4f", duration) - timestamp <- format(start, "%Y-%m-%d %H:%M:%OS3") + duration_fmt <- sprintf("%.4f", duration) + timestamp <- format(end, "%Y-%m-%d %H:%M:%OS3") - build_msg <- function(timestamp, label, duration, unit) { - paste0("[", timestamp, "] ", label, ": ", duration, " ", unit) + build_msg <- function(ts, lbl, dur, unit) { + paste0("[", ts, "] ", lbl, ": ", dur, " ", unit) } - # Console message if (isTRUE(console)) { if (requireNamespace("crayon", quietly = TRUE)) { console_msg <- build_msg( timestamp, crayon::blue(label), - crayon::green(duration), + crayon::green(duration_fmt), crayon::green(unit) ) } else { - console_msg <- build_msg(timestamp, label, duration, unit) + console_msg <- build_msg(timestamp, label, duration_fmt, unit) } message(console_msg) } - # Log to .pipetime_env if (!is.null(log)) { if (!is.character(log)) { stop("'log' must be a character string.") diff --git a/R/rm_log.R b/R/rm_log.R index 3e093c3..0a6a477 100644 --- a/R/rm_log.R +++ b/R/rm_log.R @@ -9,6 +9,8 @@ rm_log <- function(log) { } if (exists(log, envir = .pipetime_env, inherits = FALSE)) { rm(list = log, envir = .pipetime_env) + .pipetime_env$pipe_counters[[log]] <- NULL + .pipetime_env$active_runs[[log]] <- NULL invisible(TRUE) } else { warning("No data frame named '", log, "' found in pipetime environment.") diff --git a/R/time_pipe.R b/R/time_pipe.R index c1da72f..72ec293 100644 --- a/R/time_pipe.R +++ b/R/time_pipe.R @@ -32,18 +32,24 @@ time_pipe <- function( console = getOption("pipetime.console", TRUE), unit = getOption("pipetime.unit", "secs") ) { - # --- New run detection --- - if (!.pipetime_env$active_run) { - .pipetime_env$pipe_counter <- .pipetime_env$pipe_counter + 1L - .pipetime_env$active_run <- TRUE - # Reset active_run at the end of the top-level evaluation - on.exit(.pipetime_env$active_run <- FALSE, add = TRUE) + if (!is.null(log)) { + # --- Per-log run detection --- + if ( + is.null(.pipetime_env$active_runs[[log]]) || + !.pipetime_env$active_runs[[log]] + ) { + pipe_id <- next_pipe_id(log) + .pipetime_env$active_runs[[log]] <- TRUE + on.exit(.pipetime_env$active_runs[[log]] <- FALSE, add = TRUE) + } else { + pipe_id <- .pipetime_env$pipe_counters[[log]] + } + # ----------------------------- + } else { + pipe_id <- NULL } - pipe_id <- .pipetime_env$pipe_counter - # -------------------------- unit <- match.arg(unit, c("secs", "mins", "hours", "days", "weeks")) - start <- Sys.time() result <- .data end <- Sys.time() @@ -57,3 +63,14 @@ time_pipe <- function( result } + +# Helper: get next pipe_id for a given log +next_pipe_id <- function(log) { + if (is.null(.pipetime_env$pipe_counters[[log]])) { + .pipetime_env$pipe_counters[[log]] <- 1L + } else { + .pipetime_env$pipe_counters[[log]] <- .pipetime_env$pipe_counters[[log]] + + 1L + } + .pipetime_env$pipe_counters[[log]] +} diff --git a/R/zzz.R b/R/zzz.R index d838159..b83f054 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,7 +1,7 @@ .pipetime_env <- new.env(parent = emptyenv()) -# Global counter for pipeline IDs -.pipetime_env$pipe_counter <- 0L +# Each log will have its own counter +.pipetime_env$pipe_counters <- list() -# Track whether we’re already inside a pipeline run -.pipetime_env$active_run <- FALSE +# Track whether we’re inside a run for each log +.pipetime_env$active_runs <- list() From d4145c93235bf398452f865afdd35b5334b1644e Mon Sep 17 00:00:00 2001 From: CyGei Date: Sun, 28 Sep 2025 22:48:28 -0400 Subject: [PATCH 4/4] solving issue Add pipe_id tracking for time_pipe() logs Fixes #3 with a common timestamp denoting the start of the pipe operation. --- .DS_Store | Bin 0 -> 6148 bytes DESCRIPTION | 2 + NAMESPACE | 1 + R/{emit.R => emit_time.R} | 39 +++--- R/get_log.R | 41 +++++- R/rm_log.R | 41 ++++-- R/time_pipe.R | 69 +++++----- R/zzz.R | 8 +- README.Rmd | 80 +++++++---- README.md | 100 ++++++++------ man/figures/logo.png | Bin 20088 -> 19454 bytes man/get_log.Rd | 24 +++- man/rm_log.Rd | 17 ++- man/time_pipe.Rd | 27 ++-- pkgdown/favicon/apple-touch-icon.png | Bin 8060 -> 8451 bytes pkgdown/favicon/favicon-96x96.png | Bin 3804 -> 3847 bytes pkgdown/favicon/favicon.ico | Bin 15086 -> 15086 bytes pkgdown/favicon/favicon.svg | 2 +- pkgdown/favicon/web-app-manifest-192x192.png | Bin 8694 -> 9168 bytes pkgdown/favicon/web-app-manifest-512x512.png | Bin 32180 -> 34825 bytes tests/testthat/test-time_pipe.R | 92 ++++++------- vignettes/timing_R_pipelines.Rmd | 125 ++++++++++++++++++ ...ions_in_pipelines.Rmd => why_pipetime.Rmd} | 36 +++-- 23 files changed, 459 insertions(+), 245 deletions(-) create mode 100644 .DS_Store rename R/{emit.R => emit_time.R} (53%) create mode 100644 vignettes/timing_R_pipelines.Rmd rename vignettes/{timing_operations_in_pipelines.Rmd => why_pipetime.Rmd} (65%) diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..de20c61034f79b0df413a9ee49c8d968a06f30f9 GIT binary patch literal 6148 zcmeHKOHRWu5PhaWv;`r=3bD!wDsh7V?E;CP3L94ZT17x<5#=LRu~^9@Mdfw z+kq`Y$Rmx%ao)2%FNqxkFdO%SHDC!qlP)o9v-rm3zIe@MT+1?}(LM&4;1OeV@Ki&m zhNM7J;IAnl-|hmAaf2(A@W0<{jJ8IT^Rv<9j2KxUN_yu*jWu8%UG#8(P4uyaeH^mf z!*0ZSi&zaEPEghi|aYQ;b6tL=RKdu>iXp^FKwvQa54+;*%L*@{=_YP^?A Xg|Tq4vXL#c^dq1$q#`Nss|tJqSdI0d literal 0 HcmV?d00001 diff --git a/DESCRIPTION b/DESCRIPTION index 69063f8..ef7ed31 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -13,6 +13,8 @@ Suggests: testthat (>= 3.0.0), crayon, dplyr, + ggplot2, + stringr, tictoc, knitr, rmarkdown diff --git a/NAMESPACE b/NAMESPACE index 39c3598..5884dc8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,3 +3,4 @@ export(get_log) export(rm_log) export(time_pipe) +importFrom(stats,setNames) diff --git a/R/emit.R b/R/emit_time.R similarity index 53% rename from R/emit.R rename to R/emit_time.R index 34dfc67..b54e5c8 100644 --- a/R/emit.R +++ b/R/emit_time.R @@ -2,50 +2,46 @@ #' #' Prints and/or logs the execution time of an operation. #' -#' @param start POSIXct. Operation start time. -#' @param end POSIXct. Operation end time. +#' @param start_time POSIXct. Pipeline start time. +#' @param duration Numeric. Duration since pipeline start. #' @param label Character. Operation label. #' @param unit Character. Time unit ("secs", "mins", "hours", "days", or "weeks"). #' @param console Logical. Print timing to the console? -#' @param log Character or NULL. Name of a data frame in .pipetime_env for logging. -#' @param pipe_id Numeric. The ID of the current pipeline. +#' @param log Character or NULL. Name of a data frame in `.pipetime_env` for logging. #' #' @return Invisibly, the numeric duration of the operation. #' @keywords internal #' @noRd -emit <- function(start, end, label, unit, console, log, pipe_id) { - duration <- as.numeric(difftime(end, start, units = unit)) +emit_time <- function(start_time, duration, label, unit, console, log) { duration_fmt <- sprintf("%.4f", duration) - timestamp <- format(end, "%Y-%m-%d %H:%M:%OS3") + timestamp_fmt <- format(start_time, "%Y-%m-%d %H:%M:%OS3") - build_msg <- function(ts, lbl, dur, unit) { - paste0("[", ts, "] ", lbl, ": ", dur, " ", unit) + build_msg <- function(ts, label, dur, unit) { + paste0("[", ts, "] ", label, ": ", dur, " ", unit) } + # Console if (isTRUE(console)) { if (requireNamespace("crayon", quietly = TRUE)) { - console_msg <- build_msg( - timestamp, + msg <- build_msg( + timestamp_fmt, crayon::blue(label), - crayon::green(duration_fmt), + crayon::green(paste0("+", duration_fmt)), crayon::green(unit) ) } else { - console_msg <- build_msg(timestamp, label, duration_fmt, unit) + msg <- build_msg(timestamp_fmt, label, paste0("+", duration_fmt), unit) } - message(console_msg) + message(msg) } + # Log if (!is.null(log)) { - if (!is.character(log)) { - stop("'log' must be a character string.") - } - + stopifnot(is.character(log), length(log) == 1) new_row <- data.frame( - pipe_id = pipe_id, - timestamp = timestamp, + timestamp = start_time, label = label, - duration = as.numeric(duration), + duration = duration, unit = unit, stringsAsFactors = FALSE ) @@ -60,6 +56,5 @@ emit <- function(start, end, label, unit, console, log, pipe_id) { assign(log, new_row, envir = .pipetime_env) } } - invisible(duration) } diff --git a/R/get_log.R b/R/get_log.R index b9e23e6..405bc0c 100644 --- a/R/get_log.R +++ b/R/get_log.R @@ -1,13 +1,40 @@ -#' Retrieve a stored timing log +#' Retrieve a timing log (or all logs) #' -#' @param log Character. Name of the data frame to load from `.pipetime_env`. +#' Return a stored timing log from `.pipetime_env`. +#' If `log = NULL`, return all logs as a named list. +#' +#' @param log Character string or `NULL`. Name of the log to retrieve. If `NULL`, all logs are returned. +#' +#' @return Either: +#' - A data frame with columns: +#' - `timestamp` (`POSIXct`): Pipeline start time +#' - `label` (`character`): Operation label +#' - `duration` (`numeric`): Elapsed time since pipeline start +#' - `unit` (`character`): Time unit used +#' - Or, if `log = NULL`, a named list of such data frames. +#' +#' @seealso [rm_log()] +#' +#' @importFrom stats setNames #' -#' @return A data frame of timing logs. #' @export -get_log <- function(log) { - if (exists(log, envir = .pipetime_env, inherits = FALSE)) { - get(log, envir = .pipetime_env) +get_log <- function(log = NULL) { + logs <- setdiff(ls(envir = .pipetime_env), "start_times") + if (!length(logs)) { + return(list()) + } + + if (is.null(log)) { + # Return all logs + stats::setNames( + lapply(logs, function(x) get(x, envir = .pipetime_env)), + logs + ) } else { - stop("No data frame named '", log, "' found in .pipetime_env.") + stopifnot(is.character(log), length(log) == 1) + if (!exists(log, envir = .pipetime_env, inherits = FALSE)) { + stop("No log named '", log, "' found in .pipetime_env.") + } + get(log, envir = .pipetime_env) } } diff --git a/R/rm_log.R b/R/rm_log.R index 0a6a477..ca56c39 100644 --- a/R/rm_log.R +++ b/R/rm_log.R @@ -1,19 +1,36 @@ -#' Remove a stored timing log +#' Remove a timing log (or all logs) #' -#' @param log Character. Name of the timing log to delete from `.pipetime_env`. +#' Delete a timing log from `.pipetime_env`. +#' If `log = NULL`, all logs are removed, but only when `force = TRUE`. #' +#' @param log Character string or `NULL`. Name of the log to remove. If `NULL`, all logs are targeted. +#' @param force Logical. To remove all logs, `force` must be `TRUE`. Default: `FALSE`. +#' +#' @return Invisibly, `TRUE`. +#' @seealso [get_log()] #' @export -rm_log <- function(log) { - if (!is.character(log) || length(log) != 1) { - stop("`log` must be a single character string.") +rm_log <- function(log = NULL, force = FALSE) { + logs <- setdiff(ls(envir = .pipetime_env), "start_times") + if (!length(logs)) { + warning("No logs to remove.") + return(invisible(FALSE)) } - if (exists(log, envir = .pipetime_env, inherits = FALSE)) { - rm(list = log, envir = .pipetime_env) - .pipetime_env$pipe_counters[[log]] <- NULL - .pipetime_env$active_runs[[log]] <- NULL - invisible(TRUE) + + if (is.null(log)) { + if (!force) { + stop("To remove all logs, set force = TRUE.") + } + rm(list = logs, envir = .pipetime_env) + .pipetime_env$start_times <- list() } else { - warning("No data frame named '", log, "' found in pipetime environment.") - invisible(FALSE) + if (!is.character(log) || length(log) != 1) { + stop("`log` must be a single character string.") + } + if (!exists(log, envir = .pipetime_env, inherits = FALSE)) { + stop("No log named '", log, "' found in .pipetime_env.") + } + rm(list = log, envir = .pipetime_env) + .pipetime_env$start_times[[log]] <- NULL } + invisible(TRUE) } diff --git a/R/time_pipe.R b/R/time_pipe.R index 72ec293..afd0c4f 100644 --- a/R/time_pipe.R +++ b/R/time_pipe.R @@ -1,19 +1,26 @@ #' Measure execution time in a pipeline #' -#' Records the runtime of pipeline (|>) operation. -#' Can print the timing to the console and optionally log it to a data frame in `.pipetime_env`. -#' Defaults can be set via `options()`. +#' Records the runtime of a pipeline (`|>`) from its start to the point where `time_pipe()` is called. +#' Prints results to the console and/or logs them in `.pipetime_env`. +#' Defaults can be set via `options(pipetime.*)`. #' #' @param .data Input object passed through the pipeline. -#' @param label Optional. Name for the operation. Defaults to the expression if not provided. -#' @param log Character or NULL. Name of a data frame to store logs in `.pipetime_env`. Defaults to NULL (no storage). -#' @param console Logical. Print timing to the console? Defaults to TRUE. -#' @param unit Character. Time unit passed to [base::difftime()]. One of `"secs"`, `"mins"`, `"hours"`, `"days"`, or `"weeks"`. Defaults to `"secs"`. +#' @param label Character string. Operation name. Defaults to the expression if `NULL`. +#' @param log Character string or `NULL`. Name of a log data frame in `.pipetime_env`. Default: `NULL`. +#' @param console Logical. Print timing to console? Default: `TRUE`. +#' @param unit Character string. Time unit for [base::difftime()]. One of `"secs"`, `"mins"`, `"hours"`, `"days"`, `"weeks"`. Default: `"secs"`. #' -#' @return The input object, unchanged. Timing information is printed or stored separately. +#' @return `.data`, unchanged. Timing information is printed and/or stored separately. #' #' @details -#' `time_pipe()` measures the elapsed time of the pipeline from its start to the point where `time_pipe()` is called. +#' `time_pipe()` measures elapsed time from pipeline start to the call. +#' If `log` is set, results are appended to a data frame in `.pipetime_env` with columns: +#' - `timestamp`: Pipeline start time (`POSIXct`) +#' - `label`: Operation label +#' - `duration`: Elapsed time since pipeline start (`numeric`) +#' - `unit`: Time unit used +#' +#' Stored logs can be retrieved with [get_log()]. #' #' @examples #' library(dplyr) @@ -24,7 +31,6 @@ #' time_pipe("total pipeline") #' #' @export -#' time_pipe <- function( .data, label = NULL, @@ -32,45 +38,30 @@ time_pipe <- function( console = getOption("pipetime.console", TRUE), unit = getOption("pipetime.unit", "secs") ) { + # Track pipeline start if (!is.null(log)) { - # --- Per-log run detection --- - if ( - is.null(.pipetime_env$active_runs[[log]]) || - !.pipetime_env$active_runs[[log]] - ) { - pipe_id <- next_pipe_id(log) - .pipetime_env$active_runs[[log]] <- TRUE - on.exit(.pipetime_env$active_runs[[log]] <- FALSE, add = TRUE) - } else { - pipe_id <- .pipetime_env$pipe_counters[[log]] + if (is.null(.pipetime_env$start_times[[log]])) { + .pipetime_env$start_times[[log]] <- Sys.time() + on.exit(.pipetime_env$start_times[[log]] <- NULL, add = TRUE) } - # ----------------------------- + start_time <- .pipetime_env$start_times[[log]] } else { - pipe_id <- NULL + start_time <- Sys.time() } - unit <- match.arg(unit, c("secs", "mins", "hours", "days", "weeks")) - start <- Sys.time() + # Force evaluation and calculate duration result <- .data - end <- Sys.time() + end_time <- Sys.time() + duration <- as.numeric(difftime(end_time, start_time, units = unit)) + # Generate label if not provided if (is.null(label)) { - expr <- substitute(.data) - label <- gsub("\\s+", "", paste(deparse(expr), collapse = "")) + label <- paste(deparse(substitute(.data)), collapse = "") + label <- gsub("\\s+", " ", trimws(label)) } - emit(start, end, label, unit, console, log, pipe_id) + # Output results + emit_time(start_time, duration, label, unit, console, log) result } - -# Helper: get next pipe_id for a given log -next_pipe_id <- function(log) { - if (is.null(.pipetime_env$pipe_counters[[log]])) { - .pipetime_env$pipe_counters[[log]] <- 1L - } else { - .pipetime_env$pipe_counters[[log]] <- .pipetime_env$pipe_counters[[log]] + - 1L - } - .pipetime_env$pipe_counters[[log]] -} diff --git a/R/zzz.R b/R/zzz.R index b83f054..a978632 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,7 +1,3 @@ +# Environment for pipetime .pipetime_env <- new.env(parent = emptyenv()) - -# Each log will have its own counter -.pipetime_env$pipe_counters <- list() - -# Track whether we’re inside a run for each log -.pipetime_env$active_runs <- list() +.pipetime_env$start_times <- list() diff --git a/README.Rmd b/README.Rmd index 176c7aa..7228b3e 100644 --- a/README.Rmd +++ b/README.Rmd @@ -9,15 +9,22 @@ knitr::opts_chunk$set( ) ``` -# pipetime +# pipetime + -[![R-CMD-check](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml) -[![CodeFactor](https://www.codefactor.io/repository/github/cygei/pipetime/badge)](https://www.codefactor.io/repository/github/cygei/pipetime) + +[![R-CMD-check](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml) [![CodeFactor](https://www.codefactor.io/repository/github/cygei/pipetime/badge)](https://www.codefactor.io/repository/github/cygei/pipetime) + -`pipetime` measures the runtime of a pipeline from its start up to the `time_pipe()` call. It works with the native R pipe (`|>`) and integrates seamlessly into '*tidy workflows*'. +⏳ `pipetime` measures elapsed time in R pipelines. + +Insert `time_pipe()` anywhere in a pipeline to print or log the time since the pipeline started. It works with the native R pipe (`|>`) and fits naturally into [tidyverse](https://www.tidyverse.org/) workflows. # Installation + +Install from GitHub and load alongside `dplyr` for examples: + ```{r setup, message=FALSE, warning=FALSE} # devtools::install_github("CyGei/pipetime") library(pipetime) @@ -25,46 +32,67 @@ library(dplyr) ``` # Example -Place `time_pipe()` anywhere in a pipeline to measure elapsed time from the start up to that point. + +Place `time_pipe()` at the end of a pipeline to measure total elapsed time: + ```{r} +slow_op <- function(delay, x) { + Sys.sleep(delay) # Simulate a time-consuming operation + rnorm(n = length(x), mean = x, sd = 1) +} + data.frame(x = 1:3) |> - mutate(sleep = Sys.sleep(0.1)) |> # e.g. a complex operation + mutate(sleep = slow_op(0.1, x)) |> summarise(mean_x = mean(x)) |> - time_pipe("total pipeline") # ~0.1 sec + time_pipe("total pipeline") # ~+0.1 sec ``` -Insert multiple `time_pipe()` calls to add *timestamps* along the pipeline: -```{r} -complex_fn <- function(duration,x) { - Sys.sleep(duration) # Simulate a time-consuming operation - rnorm(n = length(x), mean = x, sd = 1) -} +Use multiple `time_pipe()` calls to mark steps along a pipeline: +```{r} data.frame(x = 1:5) |> - mutate(y = complex_fn(0.5, x)) |> + mutate(y = slow_op(0.5, x)) |> time_pipe("compute y") |> - mutate(z = complex_fn(0.5, y)) |> + mutate(z = slow_op(0.5, y)) |> time_pipe("compute z") |> summarise(mean_z = mean(z)) |> time_pipe("total pipeline") ``` -Each `time_pipe()` reports the cumulative time since the start of the pipeline. +⏱️ **Each `time_pipe()` reports the cumulative time since the pipeline started.** -# Logging to a dataframe -Save timings to a dataframe in the package’s private environment (`.pipetime_env`) with the `log` argument: -```{r} -df_1 <- data.frame(x = 1:5) |> - mutate(y = complex_fn(0.5, x)) |> - time_pipe("compute y", log = "timings") +# Logging + +📝 Use `log` to save timings to a hidden environment (`.pipetime_env`): -df_2 <- df_1 |> - mutate(z = complex_fn(0.5, y)) |> +```{r} +df <- data.frame(x = 1:5) |> + mutate(y = slow_op(0.5, x)) |> + time_pipe("compute y", log = "timings") |> + mutate(z = slow_op(0.5, y)) |> time_pipe("compute z", log = "timings") get_log("timings") -rm_log("timings") # delete "timings" from .pipetime_env +rm_log("timings") #delete the dataframe in .pipetime_env ``` -Set a global default for the session using: `options(pipetime.log = "timings")`. \ No newline at end of file +## Managing logs + +- `get_log("name")` → return one log + +- `get_log(NULL)` → return all logs as a named list + +- `rm_log("name")` → remove one log + +- `rm_log(NULL, force = TRUE)` → remove all logs + +# Options + +You can also set **session‑wide** defaults: + +```{r} +options(pipetime.log = "timings", + pipetime.console = TRUE, + pipetime.unit = "secs") +``` \ No newline at end of file diff --git a/README.md b/README.md index cdf5049..2f70608 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,23 @@ -# pipetime +# pipetime [![R-CMD-check](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/CyGei/pipetime/actions/workflows/R-CMD-check.yaml) [![CodeFactor](https://www.codefactor.io/repository/github/cygei/pipetime/badge)](https://www.codefactor.io/repository/github/cygei/pipetime) + -`pipetime` measures the runtime of a pipeline from its start up to the -`time_pipe()` call. It works with the native R pipe (`|>`) and -integrates seamlessly into ‘*tidy workflows*’. +⏳ `pipetime` measures elapsed time in R pipelines. + +Insert `time_pipe()` anywhere in a pipeline to print or log the time +since the pipeline started. It works with the native R pipe (`|>`) and +fits naturally into [tidyverse](https://www.tidyverse.org/) workflows. # Installation +Install from GitHub and load alongside `dplyr` for examples: + ``` r # devtools::install_github("CyGei/pipetime") library(pipetime) @@ -21,67 +26,80 @@ library(dplyr) # Example -Place `time_pipe()` anywhere in a pipeline to measure elapsed time from -the start up to that point. +Place `time_pipe()` at the end of a pipeline to measure total elapsed +time: ``` r +slow_op <- function(delay, x) { + Sys.sleep(delay) # Simulate a time-consuming operation + rnorm(n = length(x), mean = x, sd = 1) +} + data.frame(x = 1:3) |> - mutate(sleep = Sys.sleep(0.1)) |> # e.g. a complex operation + mutate(sleep = slow_op(0.1, x)) |> summarise(mean_x = mean(x)) |> - time_pipe("total pipeline") # ~0.1 sec -#> [2025-09-22 14:30:18.343] total pipeline: 0.1094 secs + time_pipe("total pipeline") # ~+0.1 sec +#> [2025-09-28 22:40:14.332] total pipeline: +0.1061 secs #> mean_x #> 1 2 ``` -Insert multiple `time_pipe()` calls to add *timestamps* along the -pipeline: +Use multiple `time_pipe()` calls to mark steps along a pipeline: ``` r -complex_fn <- function(duration,x) { - Sys.sleep(duration) # Simulate a time-consuming operation - rnorm(n = length(x), mean = x, sd = 1) -} - data.frame(x = 1:5) |> - mutate(y = complex_fn(0.5, x)) |> + mutate(y = slow_op(0.5, x)) |> time_pipe("compute y") |> - mutate(z = complex_fn(0.5, y)) |> + mutate(z = slow_op(0.5, y)) |> time_pipe("compute z") |> summarise(mean_z = mean(z)) |> time_pipe("total pipeline") -#> [2025-09-22 14:30:18.462] compute y: 0.5066 secs -#> [2025-09-22 14:30:18.462] compute z: 1.0120 secs -#> [2025-09-22 14:30:18.462] total pipeline: 1.0171 secs +#> [2025-09-28 22:40:14.444] compute y: +0.5055 secs +#> [2025-09-28 22:40:14.444] compute z: +1.0114 secs +#> [2025-09-28 22:40:14.444] total pipeline: +1.0122 secs #> mean_z -#> 1 3.117084 +#> 1 2.710958 ``` -Each `time_pipe()` reports the cumulative time since the start of the -pipeline. +⏱️ **Each `time_pipe()` reports the cumulative time since the pipeline +started.** -# Logging to a dataframe +# Logging -Save timings to a dataframe in the package’s private environment -(`.pipetime_env`) with the `log` argument: +📝 Use `log` to save timings to a hidden environment (`.pipetime_env`): ``` r -df_1 <- data.frame(x = 1:5) |> - mutate(y = complex_fn(0.5, x)) |> - time_pipe("compute y", log = "timings") -#> [2025-09-22 14:30:19.494] compute y: 0.5073 secs - -df_2 <- df_1 |> - mutate(z = complex_fn(0.5, y)) |> +df <- data.frame(x = 1:5) |> + mutate(y = slow_op(0.5, x)) |> + time_pipe("compute y", log = "timings") |> + mutate(z = slow_op(0.5, y)) |> time_pipe("compute z", log = "timings") -#> [2025-09-22 14:30:20.005] compute z: 0.5077 secs +#> [2025-09-28 22:40:15.460] compute y: +0.5055 secs +#> [2025-09-28 22:40:15.460] compute z: +1.0116 secs get_log("timings") -#> timestamp label duration unit -#> 1 2025-09-22 14:30:19.494 compute y 0.5073 secs -#> 2 2025-09-22 14:30:20.005 compute z 0.5077 secs -rm_log("timings") # delete "timings" from .pipetime_env +#> timestamp label duration unit +#> 1 2025-09-28 22:40:15 compute y 0.5054879 secs +#> 2 2025-09-28 22:40:15 compute z 1.0115728 secs +rm_log("timings") #delete the dataframe in .pipetime_env ``` -Set a global default for the session using: -`options(pipetime.log = "timings")`. +## Managing logs + +- `get_log("name")` → return one log + +- `get_log(NULL)` → return all logs as a named list + +- `rm_log("name")` → remove one log + +- `rm_log(NULL, force = TRUE)` → remove all logs + +# Options + +You can also set **session‑wide** defaults: + +``` r +options(pipetime.log = "timings", + pipetime.console = TRUE, + pipetime.unit = "secs") +``` diff --git a/man/figures/logo.png b/man/figures/logo.png index c2ddab794fe9e6e53d4e08335fc6847aad63b3ec..a00a45de1cb1941b98a0be56f9f88ff4d2749f6c 100644 GIT binary patch literal 19454 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 ALI3~& literal 20088 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 operation. -Can print the timing to the console and optionally log it to a data frame in \code{.pipetime_env}. -Defaults can be set via \code{options()}. +Records the runtime of a pipeline (\verb{|>}) from its start to the point where \code{time_pipe()} is called. +Prints results to the console and/or logs them in \code{.pipetime_env}. +Defaults can be set via \verb{options(pipetime.*)}. } \details{ -\code{time_pipe()} measures the elapsed time of the pipeline from its start to the point where \code{time_pipe()} is called. +\code{time_pipe()} measures elapsed time from pipeline start to the call. +If \code{log} is set, results are appended to a data frame in \code{.pipetime_env} with columns: +\itemize{ +\item \code{timestamp}: Pipeline start time (\code{POSIXct}) +\item \code{label}: Operation label +\item \code{duration}: Elapsed time since pipeline start (\code{numeric}) +\item \code{unit}: Time unit used +} + +Stored logs can be retrieved with \code{\link[=get_log]{get_log()}}. } \examples{ library(dplyr) diff --git a/pkgdown/favicon/apple-touch-icon.png b/pkgdown/favicon/apple-touch-icon.png index 87344493b44a850efd699005d0471f5faec814d2..a761e85ae04834fe93f12c5e5fddd893c04354ee 100644 GIT binary patch literal 8451 zcmV+eA^hHnP)sgAfH3@*T^2#O%P0)jxBbWfX{|2bcpo22)qP1_{* z-t;@q^FGj$kelzmIXU0?-g6GacxV8y1*lOI$F?%wHcDt}A{r$$wSY28XsOs4%O9|$ zd<#q~T?wyOehwwpay$Xkokqa*CJ1Zu23i28-C2 zC?}(Y7R&yy7Q)jN??9$$fsM#F^1!ftD1Mx+9(QV0^cHk2{J5b;R2S|0l`I8gO7 zjj>&g653a0vX;U6%H7bb_%B>&k$89lgw4nRHc06ak$E0F+LhQXjk959>2vU9)lnLX z*o+d|+g4_+Bp#U~vN0bLza0-@Gg|{2+&Cf&dhDfLA?2)t*z?NP!IA2-(9CTsJt_2( znV|~aGVg=z;w26u|8Js=$RR4P5Sd5pL@h);e>0@~ej9nc4C5S_SNbCSRDHg=ZXLH$ zLO0QHbM|r7|6p+O!>%6rw${L^J&Tc>3RRj8qSy6>)T_61dF=VbW1oR$W?Lzt8){8pqbcKO6W#}7D(h# zCCeQ|J~0*acVz;rRf|Go7qASd+eJX^YuTK~PB+emd&^#dGnUJNzIohA3EcpXTu^lw z#yWXq%r-qa(dq7zxjV`thtcIvfRxeLf2;&u#&Wxb7+xr zex{AcaUr6U)+3MIA=2itYlz*+bQe5bz777g8X>@p655^NSMyg@$KkfpRorF|(_|5U z?+!|X42UcMO-}>F?HC5Bf7*!M(X^20Nv>E6AwY~0TF8!DeuFusYe{~W5c#*6HX_Tx zBi92woeb_54+&q6Te?FR=V&eNn3G2#=cZm{ErbY>k_LJoTEG%0Ot&MYRM80}EM8A*)s+M}u zN#_rb9Xc|V=u4bEHYx&9haxj;zJ#`W5zRg#BoYn`^yaorvT(>P*>scpnQ zIgL~HO)GsCzOFtF7XSAYkvE}{$eSuZhMp!z-5#c!LdT{7qq4OGpzzNcDC0wkU@PU! zbne@6X6Y(Y$m>VRsyqpeX`^lC{V>p8?o^adv^>W!uIjigEmBRUw=!`SZ?5*rna zJ`6?VL1;`1VS4D6;-%c;V9ZA9_Cm!eccNfCBX+tDqF%`2s%Ow+-(9xBR~72gCbYvN zJ1VJ@k52*py&Xwjw5hvvb!H?*X2aH?v08BS*jS;SdfDc&Q3y7#bRFrs8t{b1uO#fe zd5cpeb@DG$LBFUIC?bNq;vF#ql6rj>q~6G*xZ&X%6y||`NtdRDBI!DaUfY+8vD=yE z!9(R+yj2z^EkYxa_f&mP+FWr3sCFXjy+dR>v}4n_4+}-UXKP@}hwz8HHhukB27)?A zyA<-aHO}=$y`wY;jdgpt3&wIMOweAl6JxjS*yTib+ox;$7HPB9N<=gv`6$f#CfICXpa4|9|KwaCH?0Q9CKnjp7v9sbyV|csA?rB;K8!JC1vIo%!{cOc{N4e8w z81#2g7L~4U>jmoOvZoes8H{1x(^Ol|LT82<0q*D4#p|Uhv=93*(#}Nxf3Nj z(+Fa#6%clN8%R1jnUH!>*+%~p+Gs6l+Y4`B0>X6KRL>f z?7%or^y(Ovg_zf}dDoV5={8UWz}`hqJ+yBYHvGQM{KJQ$Jkh;0ra%aYhM%Q`$_*139K8_L{Jay!^Op8dLDUhlS`P%@D2+>-E=L-1l=x{xh7wwK zK%qL8bn#PV{rnP3>xEK?#(W4J-$L}YVJM+x2qg=#Z{5Q8(wB3|q*q_QHr81t9+|{@ z?SzBlNn2de*M{*fXbkPAg$~Y6Bq_Vv#EN>Zk59d{ZcckrO;Y=HQOF}U`4~!Q8AHhu zy#(*b`P>XpCWiVhA zxVSioii#r8YPAp&5(2@&^_QOo1qG4E$H&K$=Y-A75cJNvyD~*z3&uyFA%`Cq8++>| z>~qWjbnf(oN9E5w_Z*a#mV(J-f@{~V5&Zu9?{MM51vr2HJe)XjqE4JWdzL)Du&@yN z4(<;L`vqR>^z?vs9(pbh{UVi*`eVVh(=)ir3YUuM2f9FPY%C#fQ|*SH{(e*WarME4JP!Q`Ewz5+YtVV zkdu=GR;%Y@8ZKVE2vPmg$V_scvhVdlepU7{UI6CcckS9m(wH}H+yJA|Nd7!> zva_?@ZU!l#rQ(U!WC`n(ho``!k3Q-VnbC8l3~VP@{A$=SET9DZ zOg*3;S_%aK0z|}2MT=JHP+3|3%g~{aR9E7SYsb#LM)czb!@C^L z9GN8Rp`&WG8ovAPJLuT4V}qYd2`wRnVgZ1FCrk!AAvz(CgN%1Kk2)393&HX{1Ui+#)m+~9o9`^X_nBx(~v`gz!=y*{KmxtpPde>lrTs*aI2f9HDRJ( zJJSR>Z}eKUXhE_Zwb8$Sf4F@4G9`3C6abj=ZFBhq%B$og;AaGYb%Ix~Ugc7CpMCZj z+58q47rUUOqy&nJiYTGw25f7Pe2SlA76OW!)Ey&5zhBK0t~rm$RSfiJ|%n#$jg9im7jp0sRu~tZr!@^eotd)xfcKksOVf!m`A#sihZq& zmoaJ5B+{p(_U}VOL#f(MwqO~ES}RZhP`d+vfO%)837}aHi9_8c98xajy7kV%x5!h# z&rm`)Qz%$6rzL*>SRQb!1y+bRE5hpaFm&ip_y11Sb}|6V+QJGUh<$C0?>Z-8F1q&b zQ&Ljk%$YMJmZpT3z>T6{nv~_h6GBYe+0%QqK|M4jnWR2s5fKp(9UTq(_wR=xLxzyQ zJ7eXbEfNj9AH%CL)hyC8?iw0 z(rk!|v}jNzYx#uMsmbI6Wn2g)w49)b(m?Wwsh(A=T)iEFx<-qB&5Rd;eXYaq?@T_Z z&V&vflLkrOO>`^Dq8?fTH&5`!{H2p1c@sY#E!bTtX7j*+O5V?H z!k0F6A%SEOVu3?Dum*bpTo9^^kJ<@^k8Bh_4?r~RR&h0sYY1-&!oqtW{=Sg?RRE-b&T z;Nv15?-3AQS`nrO{i03~|M_T0IWvP43n%Oy1L1$W$!*HcmC&?5wCFbxckc0fMhSOC zYM~>KS+!~vcf+v{G|!WtoJM+ji2YueCL(%u79^jV4v{N*g6__Cq=7re)0l&ft)p!N zCA5SPl9NmdUu%;z`sMz_>#{5hJ9g~g9@-??R2FLB@2dKIfB^>b*8N=Qe9)LgN4-=cb0(4_e4ehuvut^T-upGcq9djlpCC zO!fpd2pyYd%eku*j^7Isnhp&TcM8@UgZbY1+APp?cXSWJF=yD&5KH-8P8841;5|3t z+i|j)>hHQKLPFy- ztk$htyZjz|Mq>`T_Wyw=ip^=xH$w?6{tZyI(nHGST)|o2xH)ouEcT+np2@WdZLew( ziltFkEcSb3ya|>i8$+sxmM9`u_U6aVg?SJnP>F(@LTvcWBQ$<6TIxx@nisb0$_Xeh zt%%Y<;-Lv{_XjlO5L>`6G<5#6(Sq{Gx(JPk-Z+5&;kc0p!2=QkhtSc%TQt~JTO79 zObatAfgmkq>HsCQ2&0b^z8c3D6dj)e3Vq#zqH*KKkq(@L2M@0MHPi}-`*!WmrvoK&HA1@XU-f#Xq*sL-(y2Yr3y+>F|#5z=@<`zA53*CJp}iQ zhv4i)P^IbW9l=4f9R9pPDq#UX4%k%2)-TFmv}h3_^u71qTmNfml!C>ySV?V9jY%1* zmU@W)&nQT}?%3dBN)l6dLa{ZU(6nO3=Qk;2Sh8U39PwBWkLQk{tyr$234I4Ii^qP3nF>}I;*N;pBMY#LAJVqj&la%qHf@!;yvokU27I{q@(uYPAwV<%0_z?(IK={pQPG@82OVLYr5YFa}CJ`(ON z9Xv3BRD6dFO(t3tJFr?Mc1yP7cl}%?wls$J!_5im91W>|@--IG8*Ig|?w*&Gl?A6y zpLRPy2R-&DpL_yQQBifiKE}*KUOIHVuqK3&0LbCc^*mCwQWtQe=?* z_*4II6u;I6h7#C+1CO~qu}haOkwX`(3K#tU!h=Z1f1axEb755Ep?E3 zh3}m)1QAleg@lBVc)6;o3L0W&vl$+Fc5&=kW7tQi>@f}1JKK?iyPfS%@|eYd#Si%zK4&#--{OY2*uQV9zeE(D{| z2;Q)3*RH|z>C;`>9bl{;`D9N)FRi(`?%98gj6ezP!^I7MsEZ(ha0hRH437JK=bd-B zl$^H=vmjfyZY5PN&c(FJ7x)!2G5>NuvxJcuD4~6{u!=~H;8#2;epTBxV%gc*aN@)X z@TL9o%P&OCWZy7Gy>PSe1c1)cE&yOCp~YQT-2$7Yzy(E);@1Zse2^TF_`@nIE8(%n z9)sZEU{Yl+v`LLx+gEflGL+EL1RiE2{mAbO8vn%@h&IH)_U+q248sGO)@@ot^eg=Z z4|(bm{V*~C4LN+Us6pLgAol-mf!Ke$LOUW2a&vRxfd?KSm^*ha%$_~lEpVe~f9#Sa zOW>Jjo`Kb?SHq@Fn_%vN{eWACy zpIsssNP^I*mvTXw$QPo>8cq!cg_;VA4yj)s(>UlCcM^}#6<~($rbRZL?k`gzEVqr@ zYF-Mu2234mfSQ=7f7}eImuzFCmzBTae?p_}srnxJ7eBxqIH257JGGVDB1j6l28=V2 zQ^FwX`J1_U=;_8gU~1_~_|5XCID|&4gerK;ybrRAmvEbugfGUB&XVqWR8TbUHBcpK zZ63L%{aLzkHcT&l7XDlHGgv_|r|&;P+pXAI4zE^z!i6DNdl&!dXj{uv2`nN7BZ>Te z#KT>Q$lvb#rj@RQ{Z&6fHCXDRm;VWEw<2o^Y^W@NPNus!V&ep)kP)fep@c7?=@mA z4|}x*4;8NcqsVu^2Bv(_-Ru2YMVu9bM8>%>_SYIw@^{!*bqp+Zdt~Vm+HO~^MetPl z+YVwE=0W@?qiod*K2VBLLg$N4Xfmg8K?hQ9h5vsGV?N}REQ12`A*h1t#?VMQgmxwN zHZByw9&V&ExF^5%j1pR&gjVR(SY5T35s1|3Wb zIB`wPKeNdUJFgIWND`Sym0FZfQRLwo7@J6F6$`pK?a9bCJCXYp|BVp2#9HnR+DMns zcDrP`4iA@ag?6TSwney+2QjY>Bz=;bLTEhP!N!IZ;SE{?%s@1Ft%H^1+`+ls0;X@@ zsQiK)ym`^2PiVWHu>219l)VfsjCVLZ_NxOy-Cnq6k3s@#pkPV)SHixr9Fg&W4T)T8 zt?&g+>kNxK?h<>pzY5XVl4Q;kivScC`W~b~##sjpMDn2CV4t_BC658Rh z&%vD1wb06Vr%m&FVJ1Yc&XPs5!hj-jPO_~@WlcBKOw$5*vf^!W&frIrH=&*FX!SWF zC*+8IZU#gw?M4~^ihjcb7{PtxZ63KMM#gmO6XkEiW$O(wXb?DrwtMU^tB%2p(q|o2 z8fT_M#L}*0%z@Z9Kaim55lgy+rq%TFYj2tlPn5p}7cJL8L<=lJI}>|v)lnEz^05f60*MKq1EnFf$q-7W%RHVxp4Z!ybsf7z>W!EzNOWPwd+yP@Q8xA_neyx8;D zDd%UBQ>(@t6f`T3+&+SI1GNwP%rM>we=U0z&RG5c30m_YwB1nfQeZv|BTN47(ij{C zGHj4^+s=xCpv*{{N3J0K~36d2ZQ@gvc_o=1pj4V*j&p4|Fx%;~@68<3T$uBcQr=3PBN}A)92} zQ`ieo?<}=>WQ+7Ya&4o8b~Y5utgHACdYTqHV(jlGf_7S~fb-bO*x(u>&)^DBCzm`8 z2dhtljExdn$WV8H`U9?zx28fJXMxB)#zsj%#KT?5+(i3(8(Z>tW6GVRXq3=(nbBGb z>nnCUh>c}o{}~0rgA#pO@8}bc98=?w&)B-9;$|4rm>-xAHnmDbN=6Coi51llo2yVS z%p=FXa%dt>>h>09y0rZrS+X47H-AeGo&wA$p&Me@sprY^x8Ww!-8OPup9O|@huZ2L zC8ov3m|r)yJy*Af9yzDvQTV|8Eou4_phgMZ*m_4iEyE_1cCW{IY&TP?{7Gc(%J7u{{h>gd=HjkZW^Vq!%{wK0Z0op08AmOWVq-hUc&&|d6 z`=V}7%0>z84LfJK;^MLKlnp1Lq7K5>n@5}!i$u12WP7>OYn6MN6Orvk3GGcgWw``@ zD|;1M*VH@W;LVs<29V=quM;^)K`N;e4&2HS8M85KD?WhhR{xB_kf2dQ`@&9JF2mxo zja>B%HhYhHwvTs+jpa_aB)NnZHX^?dh5o7Ald@4l`_c|q|4IsZ+ZgBChJMJT~ekCY3zRg$~KTPJ@U?x^b-+G(BU% z@Rq|PV_Fc~p^038DhH#47RykY`QNIah{6q(ZiLvUrbAr82+|D-f5tT6ePx?T_C$6< zPH~J9S_;Jevg#;|D|v$R*tm&ABA>8a6#MezW|YuUG1OP=G=B}ND|W%J#3NIm+z6wD lrWQ~}2~7fBBF-qZ4g8!YV;Ppj5b6U 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 diff --git a/pkgdown/favicon/favicon-96x96.png b/pkgdown/favicon/favicon-96x96.png index 0319ed9c2ae35d78e814c3c1f1e67f6dc5039e11..5f21cd966ceccd9c3d404a5fbdc99d6231aaef24 100644 GIT binary patch delta 3826 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 diff --git a/pkgdown/favicon/favicon.ico b/pkgdown/favicon/favicon.ico index f2c463f924bf8a8b1a91b6113453de92e6c35f6e..dc51c2630124a7bcd34979f064c824a7f95a0e90 100644 GIT binary patch literal 15086 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 PzinBJ&o=~~W?laS^~JC9 literal 15086 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 z \ No newline at end of file diff --git a/pkgdown/favicon/web-app-manifest-192x192.png b/pkgdown/favicon/web-app-manifest-192x192.png index fb0e53bfcf0738a7c363abd735d0ea951640e0a0..a7841a45d70f7b292884a91caf7288dc5831412d 100644 GIT binary patch literal 9168 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
)KNmXeK>9*O zn05@W*qlPz$U)Yl*2@!XD>EB*YjvQH5Rlgi^evAbJ;IV&XQc`JYx;>|pPZM1v~RJ- zNMvQbcbyLT6^?DEU;AqOlGLRa2Bi*E6-_`nmp;r$$VkTk2Mu_9h>3{l1uw4h(tJ3O ziC9qR$I5rAC|UJXKjW73(qjalw z`VneSw9M|Fy$BYDy!Rn1!|uonQ_anT1(N*tGmY1-^%Q&JrJ%oQQWjX7nVV~ObC=&bBe!bU?n~Gd2Y3GVQMi!TwKs;05FO6YU~hVVy{q1u`U{KeqQy6;RQ{b z&{fzQK|4BQa|9!)l&j4Jr?9ue+#A-2P(-Lc$L|L*&RI^fv9ZyT=^v|&Bq5A%%dazE z4B{g;1JqRo73Gh7z;a6%;j2wEtOb8O4&pn$O_{8j zLy`fWuNE2Jx3;!f>(lrBI=I{QLvl@ljfX1#+FFc>|MD`QRoAB!ZS-iBJAZ9c^mp2p zw%Hd36i``8gy9lsIUIdT>02xQ3HktrF?L#@a<%!rTn7;ck)V1sWu1x?|9z3!@A%hB zdC7igauiG)a|PLsc&dQTE^P&ArJTXZ!<+j4#=00lhpERT#MExwVAHD`J;Ebhp6y52 zdR`+yqfcb^Mc)GeP~2Uv*e~I_ljbC)XyOmJ>oW{)0k<$!BmR*fe1~`4W$RbQ(UDgk z06)DW#>j=QRH}Qz0DxVer>}6fJuZ@lb3UGqBLO7aq!CI4R*hhOHIZrV83`tI+C+R5RIZwwLem%4}@Z5Kv&V*e_ z%-FnvGB7^{eDdtBafw4-NA+--OXks$bSPdZ-p9JLwPMPv@5Ob;hr4_CJaQG@v`!CR zhg`xIx|=>8kV=V80Qh%JMRtOR;(=ie6$dn2W*1>64jTEfblPW-*J;9uI1JU*Madv0 zBF{?>5Oq_29pSGm3Cb4PFEwAe1x9Cjhn z=vH%*?YBeSCgkYUd?ft!yC@|BJmKa zZ2~PUx$97zxMLcSgOyn9icJpsT3Hb`!J1ILzfC-XL@{e-XyRvJF(^7|1_mwtfGX5# zxhuJ;Ue3{6D`RBj!G`7dgAhp9h6Qj8eL;WXTZ}cl>@rYVUP?hr1IF9uJp$ke(TvkC z^@;v)e$d*TLwi;5ObyTtsM>9UiWR&Sz7>A6uaUQ~w+X zt=P8QKzvBb5;}sP_C5dmB3pkyKQF8CHXUAhytag<{#}{4p@s7h5Z2A6d){M)a{FC? zaF<2Shj&yK)EqSboCn)gHd9l?ZeA|Hu^--%oag557!XpDJt^ld1Ntxxpl+h6*!d)+ z1Y~5lCs_B&4gQ*%7b767Zhxc+3&h$6t;hMEuc@rZ-hi8OI_%S^p_N|}z1M^+C5o}7 z1+7l1-%&K4JYL%nfjE{dLT@UqLA|5X0(KZR3k$aszt~}|&+&67Pk9sg;BU*q z_@0cIe$iDm-pA!zE;9)S7u!yZtDitpim2 zdA+%Vo?=xz*+bWod>)ZQImd%fPEz0ro!@?nvHeR$b;TAUK;O~puahHi}=IMPXw(VAL0^+sHR~)2`^M7wslX0Z#$sIQ_f!i9|J8OaU zxEX(~xX;r6=g)_W!<8>O{cB%zm%jnE&0!Fz63&ti$Q=gxBp3y*6DFE|t6>R(1~!6d01MZN4O$Bb@oPapy|hMEwcUJmqstD_{S6`>O(jQK3f!gId2t+z z18ss%6VmVeZ;p+SQII$-gF7m?(mU5*?*5HWJ}Xxoa2~+mprE`6K157-Ri(QTU612v zr2!pz9&B(Z75Nf@({?8QLrD#QhWxKzh4r~Um$rVqr9x8+;t*pnJ>^-g$fUstFSgL6 zBt4N`dAF$o9*2X+@&5DiE4TnZ&+n|fQ)Hmpq;tbc#B2a*1lS&bI4LDyMUgOsd@wPz z2%#y^6u;XnVRYJOL@2nhdfYQ=^#79x{Y{-_1j5Q*$jQkWtKBnYAH*;#pr1<^0~KIn z?0z8m3NGjk-@p_BxBDQB$n@VmV2D*fBdO5w^6@1Dd3Ap_@p?kU{Vrd;|J?%?e6Bqy z&-uax7=zFz#((2y+=&8|-Pz;ZbcoTzgPjEfYb?a@yyNpwFSg@djPErg0rPbQ0{9`2 zgbvqk?9&avUoxaIuctjrEue)y`PqXnnV@510yjyIKnz4c{@A`57~CXz5Vu2o~B2Lp}KNfY)66>zqc6eD|0h_e`{xxC`@K;T2a634{;vy@Ea~-KU$B108;G0-F`9v)G8bCX=^S&U+9=d_aj&b< zvC9{*e}d=!?&mTi6VQ#~nXUl+zg16iRlRZe>PldXQY~_|YAM-<@xO!YQlY|=Cqkel zcbC_#IN82?UHB;o120)5mr`$tNEv~OW|O)~tpfuLR>sRWM^DEqX%zt&q^XEWXr-k- zcaD9O1!PaLzd<^f#BRKTy=14oYsYnM1fx)|Jsgg{M4JUDXP|@SRL0`gVETGU-cm+D zEfxXFZ&3L_n)sS619ZIn{OLgIM}Py6r^h;infmJS==e)kxrThtqXBmI+mndhb8CwD z%kaa#&_A~jWABfl)jLnDTTyYjyO@+_Yzq2bYbQ0HyJ9EhKYwyq_4g@-=wr7f1o0sW z5b%rbxMvj%E?ay=p^)H{di)f&(cxMuISKR?e30OMc6Yaz?p9U0%v8e+dUBs|-q6&< zK0*0@Z2V)P-^&zkZgKiJX>q9;U-gYMPW_Y>;x#1hySobn0yULBc6OIbttPphj?aCk zQ7b0{8wJG{W}~F|q%Cjg-pE)NX*;Zr6rMjv6I1@{(TW!UC)J1L_k_9cd~S|uT?$y8 z9Q+XpC}b021hM}4zo(l=a$6_r>)PROkwVq1ZO^mk2 zdEDt@`|ejaE*%jaQQu$him~v|$>Fo=y=`N0G9>z4wqh)%)p{InNsOhZ>Mf@n!`|c^ z7*25iU>wPZenzF5HcSFg?LQ}VmH8^Ok}0Bn)mE`CX=Tge!x342xkKHuYm(){%C}e= z*&md;^B_J3td4@Bax5R3f=$&K{09G+3|nLqk(8t=%Ul)Uw_cS@?~yNIaSaZ z7+pucYP1Yi+sgyF`zfID1t{;FM!_P8j;!w|6&Oe%$54$1FG=**m;2Ilwbv8G9_5T# zgAth9fFoIxom<>s&c`9A_?0{~hseZL-oYv`fCHueYdcj?K+yhEK-f&!5C@`&XxpkT z4WyRN*l$g#dgQ;2ifZjYzGOdOs^JHy#*f~lWeO3_6x8e-fI*axVhbhsxc&m;6POB} zzZuv2(CHjuMNW58jp6al?(XiE)>4ymSm-UCrES1|(i%K>05W8b`Y&n2lz}>N!@|QqzPf`b_RRp=#oS-+16>Lj7A?^dv<2yC>1b)f z|2XojJzUI_RVb%cyI_U3qq@mDIB2Z%u)5l_%y;9nCX*cB*3BGGlLyOG3oZbSHT_N( z5D%P3=RR>ja4fhpU=^@Yco0%fAlK$P(p+h)aDXo)t z+Txt#mbPe*-<#g<&%gg+_Yl-Ox3;}(1dy4*`X492yoiYx!b_j;kIMoY!Eg4t=)?l> zcCAj|#RHUM=EAY;cgZYom9htH8=*P#fDVgsV#H{we`8prBg&DYQ6BIF(VQLzTk9#_ z*{ec;YpotL*6$;zl zn5l(b2GGju+NvTTc+!*hgfnGswAP-diJ<9Ozp0l8%1#N*S_Sqt-MJgo%jphCaGhqwNNOSFLB4b&Hz{pAy70w;0?L_K=6Kd^~0ow zbwBBYyvCv9B4SkEE-gL%W!=(_jLA6+(Hu$}O8cVj55f`^U<~Q&#|R)EnwpA?UIHCG zJP+@FQw3>R*}I#Y#ozqD1np2AkN~&-=*4@;4AOQ2%m%{r5iPJR-ZQ{+vW?nVm;?Og zUVlv$HRb2x`qV@(@viknRqe#Yl9!=zng_eJCiV}sy*?H$Xp=<1FooX!zy!byil`{t zsuuwEIn)-5k|W!%Dv%%ZpZG8bhWr474swIF5GXR>f6XqKM8AV*zWWaEcU{Ce(CICO|{7sQCD{Bf7+P3ulz9 z`cgnK2={$%D^xr$@uy-F*yhJd6UbBE%GxqDku-%3n*QapgGqwOmISEzq7|wGUM>k4 z*4kYQ>o;$vu-<(4l3A)nn83L(g#xUT;qN+YNH{oHbSoK8bv#yv9!(xzHZDtUvbG;7 z$i7>9NkBkvPi+c>;I45{Fm&|R|88e-IBzyn1qcusqxM@k? zzGQyi-e~p5*+)T(ug~$`xPHB9uWnE1{$GsReTGp}N_}GtKnd%XyDH2# zX}tM>5(tVYIA9;|UXD5O0hF+2$M2W2Ik1VgoxtaAQW3sn_O1#9VZ&*o;Z~CLD~pib za+BkWDdPiRvZ|=K^CF#Ti}Z2Uzqnk~kP*W(m3BNTKJ~|Q=|4E(L-#u+nJ8fqZ%7pv z7X{qMv9`1&{;&E}qaPOxwons32kI{!J3GzXH903W`LNxE?vKTF&o?lce7?M>tl`?V zYhB~#z|mNioON!Q@R)*)h@~~OrY_jME&d5R_UOAQGUP_bw^!8We_8W@k<9xB8OwnG zlYl2?E`J>=!xHY&pvgt&;Vx-ywSPZqXJbuwsyeP>aD6o(=%BUOLWAa@H9@LOWZqH! zzj(P+dkblG+ZWhhK;WY%)&bgI>#A6PLz!>w--QQ`f#f>7?0B6=OFCWxRTxlccK0tC z;UP9q?DH1Bllpkdwqys%(x@_0G>7=>Rwxz@v4W5S}Mjmf*jM3v2qCy$R;%EDwbF{5bG zCem+7{`!;UAVwOjSnP{ena_J(;%jnySE=JWtub+F=^qoNWXgvu#0>KS$H)Ku%BnAr zy2;14&P&~vI@ZR~Yf50^u9s)c6J&q?@!h-YB$IdR?vXUJ{;LIWT^*@^Q~%})(SI0T zVO_fVT!3FKXe2%lB^KY?bXplP_(mbE5`cB!LRHi_AL*Y~3$l5#j>+#^UdLcd4hR2 zS^kuDJt8*bl$1Zji{2^@No|cWZ}fE}H`mp$U?yEB#1?uA)5!_mfa#+Jr=as(fNbda z2TbTs=npKrEAxxh&|B@a<~c4--@*)@?@J8C$y}P&(bh%?-ei??QG2YEmU`U(`t=)R zVPN5-u0NN2aU7S7C1AtZYeiw#(ciY-^t^X0e}aG$c0M6H{e(q9DhhByJv9lL9gcht z1XT|_L1M39_#H5LU_1(dHzy~23S^MCZrw7;6>7MFSBxdiA+@$`2_)Rq3?BV#1Lo>P z9QPogh6AW9^jF}oM@4_F`l&5Bn9|J5xrVi}(A{k9efsGWPtUbRJKspiYh$|8KtKya z*s0qW7PVOS^TBI`nlxzsAm5oGHiuP_l!@8y8uwg_)7Z<2oS-8IS`O!|y5}9ox;~Yp zrQL1+>@!N3a#$P|3MeG>)uzwae>3u!ur1A)mYGS|eq!x-l9;=jf3Nzr9+}8pFhd_x z!z!KSn(IL=eI^N$^X9shv^r2jK-YX#{Q95jE84<;<~t2OPASb;o|k`oiwwYFkEcUm zRgvL^{-?q8FQnM(>dPK7QeRsgE-RHf$FOdO1>yh-3L&7tiA2qu$x6n7ti=DEf3KMk zx~~k>7(}gE<#zY-_kC>mPXN2$Q)62!Npck33zRru(m3h{b`18bD5|f$`%>(l%$TnE zAt-q($ZU|rn2wKsv}920yFPrJTUunQtxH3EdthF{kQd2da8Eu_%HkqWe_Ec9~PFu@2x9|1CQ*EmL{gMtuLY)mL;Nk2>iTtQoG@0%ty zcx@cm_@Y4`4`d+v+QTwB+-(}Ij-`aRd#<7xh~GpWF@oG7B$N!O7fl%YtA1?M0!W+M z>v31yfAEMG6~6XWWwl?Zs}jq^22c|KK2Kes|9!mD)o$rLwO+o_dly^jG(2n53*R3Xn1+A; zEWvv0bC;k{wR}ghKS9*-y^}P6KW9bnOY{aaOuaLlNl2SlA54{Gl*gQAN5A;`RUs!F z`Pow7R1>h)JCV!)B5*m$+$Fzo;rj8D8vvXV{{v1h$E-a7EGNFLfvMEKfT5(`j6n`5 z8hIj1AJ~EFj4n)6M$yDP&{g>DP~+i#weAat$vtvuZDuqW*w@ zJQ7T^nL1w5)#fYXY{8&iZO!P-yqH>>N0}@^qy!T?_iBC8J4C^d^?F_?9ef?m2062} zK#1gfQNtO-U(2@#U|`4rs4IvCtsRPNOy4diGF)i^ht3AVR*8F1c z3#ZwwCz1uew3sm#%tWnlMtCO0m&47=K{d=(dkff(OLAy2oh$c?ck9OdQ@uYQ5Bd%s zB6iHzLaIOB;>5c%>`nf=eU1^2q6_t7OigAUMNv|H6MbgMab8%%Jgy=7SO(M-EHa^K zZ|0k+84m*}e@^iV388#nmhNe2si%X6T$MJ-Qji`{Oo(TH#n)a=%waGAzxg4Zi|5x| zjnDBF5Vga_?DVe@&9?uXc?ocM7Wmy6m=T21b(eG?+Bo700P`y>UiaAgo>ri|Ph{Aw z(3ha1>T{vw&Rez$pi0aDRA6V%1=GiqeuE_-y$uyxNP$_aP(Uqz^Av1oZhqSJ#m4A_ z){jaWC9}AiKAvg72(bW*{P*zePQ(%FESg437 zLnM6w!VzLXFvPuc*|24=uHvH>%OWCP9xJ^Agxn1Ol8$tMX2AhJ$n8iHOmqaQk5-LH zn0!GAO??0{^3g|3%Nw*5W;6bg^~;yB7GU3zhcNx~juC2X2sU7VkADS<$^D11iF@Y< zwUFHe`u0H|G^H*^g8=Y{qYlvYBdpm$4AC#Uh>>X)DLl6O4{^G>_Mg`)K;+2WKqMO+ zG5F8@rF^~s?h}oT1B+O}<5T#Doe~kpfyqNFgrW%0@**v=4`0!_YEX73j*4R9{UN7J9=pvDoj`zf=HvImp%Nt;hvJiwzDmtd$V?2E4-~^L17f!yx ze2ng2l&Xkua@C5syhXgAnVVL0jrpUG`AhMIhiknH#TU<%-QH+$1HiNkz@+p!?ZKgw zJ32?68Luw$98a~=OluED?%#>Ur#XnYEDpy;>w_!&e^s4zSX5oq_J@uE5tL3rxU)k7YX5c?d&uo{> z?7Q#LzT!7;(~(tcze^uRS?yZ)v8z3mSDLm;DE~~%<3O~3?Spf?u~+ekzby;r1)`PO zH=eXuTGLVadkXEfyzX%r|4fry0;+$nTcssV#Tk-HMsSm!Fq6VzFqIG4>auTa~ zL7#VXBMHz@c&g0^z@nmZ=<`#jY0tNIN4*w4q0)9SBu-qr7Zzu1KJ z30$Tbs8|P0>@1f^!6cO*+dNjN{G8hR%AiPP`R1n8}jRwT4QkdW?K@O zfi+*o?qB~KKL6T{S0B!LCNnm^{|x0~E&kqK{(Vf!C}<7j%}-2gFns>j zF&Nua-R_C2WL6oZ@8Psp%I+bf{no~CZ}@Hv1`3_d9*+D7OG>&|*11q}7bu_8y8Z8$ zkP7Ot^)Jg>GbbLnJ%bIJ9-L7xpG@xA@{fPO}>ff2l$3Hs5xEvr2l{&lqJJs{h~Ey>p}pVd}G8 z|Mh1}o%}%B#X2ke(armFXs5h`vbXVV3dK?X;Y!9;VejB?d!28P%apSf+auRj+QD<% zSgsSC4Y$EDF=qCAZoUc^V(CTKAMT+;3LuNm?<<2v+-}6X&r<(vUr$`s)4_YE?B^34 zoIlrgrqidDI+Vv1W8$;HdctPhhm6J=w>^^z{`xiggO`DCCwKd}oW8zoskym$@-E-D zwIK$P-;^+GapW>Wyz&l0Cgp-RgpMiv??M$LV`-}2SSG({M6sx4W2K+pVbHD}$w2(A zU2(kJZd;XXpoQ)B*iH%(XwR?oG#=*lzq9=bkZN4uc*T74j-UjihH{3%BMoylj;tZ-_iP|>ySTds#T;$`OS2W@W`1KVY=jX zw_7U`^hkqwMr=x;a=yh0C<+2J6d`kTS=n)QN!)*CCxl1+1ByV7&G#hdu9BUL^CeU^ z!-*URy4LEG<-y7ulmyX>N{;s7kjwJV4|Pmx$`wg6wc(f+Tk8ba&n?*u$37zTL;rM( zvo%%c`MxnNC zMS#VErbuqsUy?KZXT8iM!kn5BP9gs1lb@jSYm^sFDo(8E>CMP zC6?!498l=U4?~;nbMaFX{%IzEfBK`;#KZ73O`+Okx5_iTw|`;4Q^;xZG%4lj%UlsI zKxE0kLsX4_)W3&f7WY4X!lrU<%DEp6;+zIlGWK++E*{ukAoJSi#hfBPcWf$hk_3UiUJ3q_#YoJS1N_lFIZf%vTMIB*H2w?&a&b;I5hph*L-^2CF*jRKHu1= znL7B-xUR|5j(S{Uyqfx#t!8?a?|d<6rrdK&eVn8HB6{-_wclB?F$(?0%6xFFm>Kn0 z2kR@tK(CkL)~)HD|aiy?IruV#T$m0|V#hZ@#h)g&72Z->%pU zNcf35h&twM+XgxxGtKs#-aZY5ANT;SV;JzZfU1=+MklVz6-Oe3XBij}bHP#L6X>}Y zo2mm%Lbd%e1p@KJjN0kHZ7>2wmn&)DoYeDDXz`n+XM*5iCI8tXnuS3C;&X6h>Ir=J zwaa+g)z>()8UqONI7)OTfD2RurT(2OcC+5%&XE1AkW^MyJQL7dK3P@zqN*GGXR<9; zg=*VDxk+bQof(K9t{15QE!AD{)dYhzsKGV);eFmRdZC;;j#=n>>;Ia0htbu5B=gV& zl8)h341-oQY`%xgzt7vOf_yz~Bizvj>LuXH9tY0z{*BotXh>Mtp|!&U!Yz7;^3*{D z026?6XTfHYo+|o(j$qqdlF$EcNmiDNBNN4?Z(!>PJr67Y@l4-0@SQDGqe2_*_ONjj zgQWKUm6R>iio>?lP=|%wLaFJ;`|Y>$V~siwR4Q}S%73}-?d~*+%oNB1|FL#20BW%u zn_$~o1BJKNz|u_Z>jL0LQTG=Q4{);uo$LUVP7As-`-`%x75Pig-h!S4+O!gEgi_=B z-kjd2DqKIMrk1wu=Gx0M)QV&AEfW3D9NKlHbi8qh+L%8**!&sj>V)S6w7>6q$=bFt zl>FzE7iY(LhTkXeNQze37A@$RQUGG13UE7joJ0UQ995+@9I3R#Dx#xRLUZW=)ISMh z%S8k4$oZ~bk-8gsg8;*@YE$NOvxH9=jZii)Rt^dNaTI*x+B(pA`}IX!5;SWxsL!1# z{N?5wtFwTMaTw6f;_m1OAP_nV6i0z`YNO~d$?i;PG!8(Sa*ubKx@D+c$zNHi|d z2gTs%Qrsd|p<}acpMa?wv`LN>=u%};K7(|;`l$;b!yTUd3w^vC0a%eDnXO&@f0v2_ z&wam=W*ui)hz+L?dxoDa<)Z$gsk*&9+#TOb=EVNltCXYN%RZm*aSZiQh5&06ePc-C zPI#;H{-z&rjktk=KR|Sr0Q~I#8v93`Y_0*8uDxL8Yyn;X?6K-swVPLXQ!~Eb1xcT% z2V%DuF;t+TVg8V?e?89NI+}WD@Pr^8nS21(Zzy*PvRLFlwAJ=-lN@h^)Wwj|K`V+b zmt-*0wJV*R_XiyR!Kd{W+_4BY{tt^_48h%Yt&Bymoj<`juZ|#_XXjhpHDbEL82T;s;e5F~FKO-v?k&A5UWN z>_;JY(`KJqxtLac1FXiD)TW_bW5e}=4FAVaz|AW?JW_*=?4}v^0yNHLltd1<&=imh zN?mSJnfQ3O9KnDTt=}i#g z6dKuQ7wT5Wa~dm-+&>glF+d%}3ENc}=EOB=R`kvojTJuLF4!!-xh4*TBXWmVGP7i# zr5==<)Fit#YF4@6pri1_K4a(10-1sxJ*w)xh5gzec)1*681ms}*x)zDe^sB99t=7g znB3MbA?u>P9=-IU9mmlB{mJbIhOfl?)AZkH|LL3G6X&V`jTVv zfnct+(i&)w1hOXX@P`8Z;tO2dL!t0FBg$gTbRbRrk1K*l9{_<6LGadLxOK&zd4~XZ|M|xeK&Q}TBx*bF)VRSY6Dy%TdI$_H8v+D}`B8qA;sbDcIZpJO-97k%Jp1E>OT_#dBl*`QCRqBd2q+IB@H~ z6vf`&-L3kcbV05MV))G_+7_=0CD|H9K&SYgP)^Z76~yTcE%e$+4;e;`W&1XMax(_X zhj=0**R2JJ$K-&|YKMEBBafdQ9IXHL>Qp7|()R&?*BHpqiSOdTaC=8I90KR=L{doz zOcbi8@16pp$esE$_h@Z!G@Ov3x3d#CKeh|)NAq)8aMJ*p0NM1t3NkB4DZZ1QrfAK6 z15-Wu);_3tBPY_6k(M9}(8r9gxJk!v;}XuOd7ELf^77{0<))w_#f{%3?ycMzh6!@u z43PP${*##WjZXQZ-K9e#JT3=IvaYVK+3?#ncs~5H0Dk#=dLi|xy_Dc9-O+iqki=5G zV%>2|l<6U2Z1z1tvtY}~+(Yd)!ijSz?xB6psR|(SRyrViwaLdKK{~>)KgmG{$)_J4 zCa|9xf>hZTwrVC6gfTeJHU4PDZp^~0qB{8Drq7KwQchFa6)CI;g+mnCP4y=MWPO7;Im5($v!q@fy1ubTwi-8I z70*mG_v@V!tgB{aJvs(tsp*$TS&qym=d)3FbsbMRfB*jd7nX`?_z&RJYeS~~N)u&H#<06g zN3Wo`$|%0qdwVmYo0E44%LAT5x0QYW&GqF{*8MAxuH4~6SNlk-=4%0OI)JsWM338> z{SS~b+s`lz4cB4NDu;wn7`_2(#;iTl*_N7`x+M3MfL7dS=WF_n-)yb(@hjx%tG(9I z3Ug^hZ|{8}LLTiK6No?#tftCW44%lm@#_^2LQdT8g|_x{pcBgj2zPhR)#8@3YpkcjYLiLEmf#i@#p^czf&k zn8xDhSKEC=xVFE;faWf!O?K*(pk1n6wosa0436eVa6=%}Qg>W{)m&hqX+b0$7#nS2 z2KfI1=H$-d@2VrBrAWPbLf1o~-v9)A=4e1`hL)+Mp3MGuMJN=nHen_4r!mrNDZFAW zIplrF`@O)%2CV1%O0v!7ouSVa6bOac{euOZX9_te=NcI+pPj4495~HB)iGaa!d81T z3MV+TEm+#v*gJ44O53!(?q1qx>3SIF73l;-5*Ej;^ErW@Wxh%zWrTKenH|c$_tMiR9GJBOG`_w z(tWiIaq0}eQ-cuaKr2iZ$qG3o@8L(qrEkZhWd*!E-0;)IdrK0?;WAy`QM95|-8(;U zU@d)4KAzpb#YFcnPhPpU*_@DLP(s8q7f&3)x`DR5)sOI)utEo&=s@V7H6i(cXb5HC zi~Hj2>?KbK1^M}Pu7qEZxOjT@EZm;f;dZDsVHp`2x$MmF545T|d>MMLRyZN=jS{~t zUxUg*biW#Ku!*W~uaFmO87>!^=tj(<3MmI#AHNyHd}H*={S&Tg9I#oYfIDCWBKAyR zen1xHQk@W5Y-1b|HKeNI3U2YSOuMwS^q=KrG-hVzC~`hI?9QI*enEw{vGQ245Daq%u9mD2ATIP>Yhhe*Id+wtM5s zr0FdN-yAa-vuBM!cYgH39}qQM+XV0lG2|h~$!mk@9q`c?ZaWqnmw~w+KXyl%7H4YM zMb3zpzE4Vg@(Hk6e|n_L)vYycH{Zx#W>nPJ@%wuamd@sFo#W&^kRL9ve~HAsjosHO zG@VQrzHEJ6Ih+ja=lzUsLU{tM;Mm@!1`|uX;p2_xcpt2!~;W4*4=9|52@ z=9_OM*|hquC%=zu85mbXx4EflLOt<8j1G|!nwXd%6L3ntFE#l$Dr4euqpfJS_0Xxs zb}(JYeKWp-IiqS10QuSaNBX#->Yi<2msUjLD=ul(b#wDKa5FK1f{{WTf=!*TV1}F5*Ko*LT zOgUl1lET#nKc}56-;qvwl>|;_=!4r0FYH-6T(vs+L^VagpeB+Px zM853}=Y$O<=T}+&L|3oQypFm(-WW~rPp2nEWO%x`+;_IH>)zYgF!12;8x-?79lMBv zhwKqO^5s4i15X7Nm@{QnRTKBi%r_aqji7!jwDBl!x+T8mnc~ug%{2X=Rk}L${h>ie z3BHBHt7XI7l4TyvI6VvIno12@E{kE!)pT&FxcITV)>;vf(6}5Nqo--{SuJ+a3 zQUPDL#ZBXQT<}7!v{rwzI1Vf8&uhhT>L~~hF#~E*ofePdU#nq)HZ$}_w|38kOL{@U zu#of+lae#Y0K%S0*>PXCS12oZ&HW6Z9MD)Z_Q4KTD(+RUnT+yg&Y`KP`Vni$ zs$}-=>S_oH=L>8l!aPEV1LSx$$<(4F7^mZ_=_qGR!Z-|wBC#-itr?0U3rFp+WQ^Z; zHF@rx*A&rKpqS-KmLU-dky56waM2>tgpcw&= z8q=%AQ0vd^kV1@K779R!X^DKE;Z(a$!Xj9nv+By&{JA{Y67o6yN_Vd9@*L5|ZLNON z5`=YTHWZK^Cw0RRN+8h{^2Q5!E7rz!0>wx|wQ=YQBcQ!cPX2+g6Z5$uS++qB(2wn( z4>JfroFI=UF*3;;4;w|JTm7yav>&Mn<4Q<7JTwEHezqPgEUd{ApHyYUpG-6|rv>?u zZ=35wq~_)YA?vg`Ngz`5P*4UQtx59&v*<8439e`yAvW$DH=7Znv!Wa&2NXk)=aqDLG-HNtg&Cniezaf2 zPZ-2~7y13g|fsc=-E0`54S9!a}Tf8Vi^;bH=T{4RpP$ zd@DuGWv&8#z&`u*1^47*+zRJefdos>of*b0_ncdd@85fZ*Nv`fqh(<+)lVftv-Srl z{n;rnaRnezx~v?&LCZa;ycKYQ;cxfM(_T+Og1WLmtm zQp?6yMkW|B(=^5AZ;=BTNa24_d+}a)Vs_S$ks?b$^&L|Xp1PeKc6XG=ea>sC?3bpF z=omZllHVQuDJe+6uPK-A|Aix^K{7RUn#Cy>Ez<@l?No#wyUH!=Z@Z;`JKiTI))6== z*gpTrAYc5nBP&}N@e##=O550bzPNj=NK2=`dvm-*b|*`ak58*;!gK9cnuwqhDR-!4 z$N5Jv2U^~`b+xvLYV4CgrrIm^pR)4w^uON7v`b)x)RfGu z(UOrB(znM$GZl`Xdrt>uL!qQx+D#m?Es#Q8xIL*PMRkU0n#S;H=GN;~*T-{4dBkg* z_LhMGJGbXMAme}C#%^x1FLbG_()lxrXn;MOMv5P2ya>>e7fccPZlp%NFcOFkg zMnt5!e54Ubv$`1&Zz%D|pN&#k2{n?Gn?wY~|8&}xtviT<#Cfh>!?6W-4F8FMUJe&j z#j{^IN(KfKnD4J}kEBh9`5?+g<;cP8c-DNrDlBkSEg$Q} zj?n_xk>dvq5Mbp@)>l{R{P{&*R1@7;@NEp?y|GdGezNttDv}_k7_6c}`cDe$#oN8Py8-^a)2kwIncZV=^9 zh2%AU>5-^~xoQlM--Ln_+QC+I(cL7xS-d#11%yXd4$c>m{=>tU1qETEaYPUF!?&{b z!7ImTN)79DMICP^+in?y`}u#)aMNO_o5auxxn#=mxe5vjChRF?!GWvx&)(18uZDH1 zy=aA{Tb@TYPe{B53H!_J{s=mvEUZQzfOmd1(AvrgnxVCim6LSE(1^9;E-+S9IWd@b zk5WNNz37AueDOVKYCQ1)tUnOYNsF9)N}jDFwdm6XvQbvwpxEt*b8vj^Udy?>M!2KA zsC6<}{Qz-}HmrNuA^!&-dX$*G2Um*J-8Xnb3*4Y{DM=qu!N%oJ5!gKE#Bp>%K|Sz; z8(-g`me?enRq$0sd!Lo-^T(p@o7#`GRrzk=*UPlT$|%+|qq;EX_+W9D#Q?+wtAW}l zZ0QS@_L&+-$DPLcRzGNKUs7hIj?eH}Q-}eSy^NuuW4U1ye-xY)`V(yb7Ub zR#vPmZyI$fcIPCIZAyVG&N#~%eb+6d+=#axdS`Rz=X52vrbpa#5Df^R_2k%#z@}w7i}q_r^jazaSaU( zQe0ssJ`4jCO8e`ZKz=)9_HK{8=6ePMWH5AMYiw;@8N>DCK zE#V`2uoU8xZeEQCR;_1Nl7*BMl@YV>_xctuhM|%$MuAr*+`;BG!t4UolHYb}oo97> zcMFQWEe0$7t~?UD#GVkO2#jVKp(`o%;d)~t;Q0n(vYafitj3*p3JMBr<0$q&rJW`b z&4BFfw17AJJ56>WgL;Pld+=+9`wyr?KWHZ@Vbm3|<{q zb-+DemI#nX$*)eD^(At$Eh!@XR(c7CC%3^djP23Yh}c<*(Gj4pD1Q;s*qM+76l*63w& z#_uAJ)Q7o^DLiT?rdk}aXvBTnElh)M&JY^F%MK0&alc-l@0%09b{@_Sp#E?9A17BS#!35{I2)G=JKZ#i^Ml_*cMy631sOa5&Y&979=pE{r%HGCQe!#Cdn^ua*ZTKE zg^r1(&MiXVg_f`{!Z!>N5fLl?%4D6g-<2RyzqPcFNo=L1d8S&ytFFjf`or#Rgjvd? z)oA9aF7)K9q-x7dO-~z)M5T7=2$RR+UWN<*nw->=J*RwXNB8w0EG%r&q31d7Nd}&H z=tl-jMI!%*`{-D-vgUs%8)%`ScZmQVW{UHT*Ag~(YZ})K_7EAb6GTdthBW1CFK6|M zyE>VPFzF&U{30@!1u`&_kb|u)ps(y|qpJF$A|Y1lrn+0Lqujo*t@vQ{6SENITil$G zRmOv}Sm%siLR8hXAWK8sknt$9f|%5qQ(uoQe~(tebe1cQsK&0=^HSTT6gP^Cp!mAr z8KtMIYnRUv%h}c1yXM>rZ`tfzP|Ol*#6g_~tbu3I_m};hq>O;i~Pa zP<%?<7POVy&(F`fjj%iGD?1qzvUcZ3iSF`~%uI>h*)Qg7LHLl)>&q>rKh`SdFDkjc z*q%ML@351R`7-$;?z1@F3~f0Th6{KrqC3^+B2alvqCNvPqP~=1g@rZ5>T_jxO6aG1 z1CNP6<4*0y0KoWB(2p@suvnB?xlLQ!KLl{D56>GNLo*Z!n;IJFHW7>;u&%&EIrHaR>vMl6n1zEG$b%Mg3^U?A5&G+v{I17hgXcI4CHvRpP*~0zFdveO6EQ(z^I!&7i5Hd6R#{Fts@iY=k_02u z!5%=1Ok z#cyyH{F0-HenJi>oSWl~2e4;RT;Mcr-gUSrDXv?lj!jRe z%OjFf7kmbAz+Tg_QIK&APv?}rYWt~Q z#zGt@{UH_md~Z=GA)y};Ej|tE9G?lG-$;nia{*-TSjM5azGdf<2!mxIHY^bhQMZw| z-kz)QDK;)nvt)spbLUNy z#y^$g`?qRQ&+g9LV8m$R2C+fv4^A3SmdC-*XM+ud-)xfyHArpKPBZ9nn)AH zrq3&v3lPCz+r!Spg=>mpOjvcdeSd}D=*j=-{^lztr{!k9tNbC=6mvWXsJn&^(?6yG zMTrhw30A_ubODlgcGfmFy<9Uj8l;(EXdo_0-Gu&b5xJ|H*0ceeoA0@L#~`ZZ^Sg~h znUfR$F{5$VtQE7H-K5Mr!u9Zh+pUn#-{v|>2O1&Kl!ChU)0Cv71vN)&YYUyHdpG8@ zhQ6$}#al42!*%t@LWe0sc_r>flb;wZVPy1_=>sk6i!X}NkoPbA{ad$D%c3h^&Wj{8 zLgG)#@hvO2!gkh2`xHlN+$s3b0U@-xdyq^7WW9J=@=9pD!y063Pn3OWF9f24J*ogk zZrqzeBH2}YUp?{85az%M&mMV42UDTcfyBvH=6mw-FZb<8ohFSt%UD$fQQW z!ND1)IotmuO(jYZob}=6F-}{KwCNXN>L|bvI8^z?Lu?LaimN>O^W1H~Cg6N|EKF3l z+(WSZ^AmFwv}w!;vI;bRzklo0{uLwlr2-{_SU2a^s;$sZ-{m#5yE+DWbnZgSCfeRY zoAmSE*HZ-BjI3GC$;*1@2VI0|yr_BOD9Gai7!EPu5^n}0kBiKrD1@Jn)MQ%6f&EE% zY>;Q^ZmyoZ2QS|HB1996Vmcj8B97}BLnVIy(IaNJ4(#pOIyJjXE&rR0)~o3uEf*R- znW=o{)3pMt_RMxa7T+VeT~pf5b)vf`EUpRK3c!t(ZMsmF9TF?^sq2%>@xgLW6|`ka zvIG9;nhJogxW*PquZ~7e+raVjp9TT4kxY*C?mnD+2KD+M01Z1-A}^04mx;p^MfpA) zYJMU@FOhZIm&DcKT*VhPD@c5EH0{PGFVSw(>~#=1*G3aMYz>}n6xaUjtMUp4GrmR- z-o)ysiz3rFlV!#qjko(^>g&ns)hM|^SwqDS2p?j=i*I^ww#>-<0>B=!okA4`Q1hAO zq&{V@ub0H(?%O$b@9|Dj|IJ?#W%Q_Z2m?TqB|z|Bs%pW@@%!fjkIoMmz5qPLE*l@C(GH}1b+za?E?n-?*tf~1A(sjr>@@vpVi=yI znjw3=JW(8AXCw0qlQ~u0LY1 z&G$Ye!+Ztge4S*tpzD+0uH06Vg%(kOZ|l6i_ud0|ZRBFApX@rp8`dwy=$G8|zeR{qrY|YrGtvyBn2%m=`!S^vQ+FLQnD<3x7Lg zkv0a`CeWNLE%@#$bhNa!gF%h&^&Qicw7ef{2~XmdBpyX)Y=vkYLVCk6i# nuak`CF2>&dlNXDF1LT(Adyk2ZkoN^D1pFz;s>+l}nZ5ge&s{P6 diff --git a/tests/testthat/test-time_pipe.R b/tests/testthat/test-time_pipe.R index 4324353..a5807e7 100644 --- a/tests/testthat/test-time_pipe.R +++ b/tests/testthat/test-time_pipe.R @@ -4,80 +4,64 @@ test_that("time_pipe returns input unchanged", { expect_identical(out, df) }) -test_that("time_pipe generates default label", { - mydataframe <- data.frame(x = 1:3) - expect_message(mydataframe |> time_pipe(), regexp = "mydataframe") -}) - -test_that("time_pipe generates custom label", { +test_that("labels are generated correctly", { df <- data.frame(x = 1:3) - expect_message(df |> time_pipe("custom label"), regexp = "custom label") + expect_message(df |> time_pipe(), regexp = "df") # default label + expect_message(df |> time_pipe("custom"), regexp = "custom") # custom label }) -test_that("invalid unit raises error", { - df <- data.frame(x = 1:3) - expect_error( - df |> time_pipe("test", unit = "microsec"), - regexp = "should be one of" - ) -}) - -test_that("different time units are accepted", { +test_that("invalid and valid units behave as expected", { df <- data.frame(x = 1:3) + expect_error(df |> time_pipe("bad", unit = "microsec")) for (u in c("secs", "mins", "hours", "days", "weeks")) { - expect_message(df |> time_pipe("time unit test", unit = u), regexp = u) + expect_message(df |> time_pipe("ok", unit = u), regexp = u) } }) -test_that("time_pipe throws error if log is not character", { - df_input <- data.frame(x = 1:3) - expect_error( - df_input |> time_pipe("test", log = data.frame()), - regexp = "'log' must be a character string" - ) +test_that("log must be character", { + df <- data.frame(x = 1:3) + expect_error(df |> time_pipe("bad", log = data.frame())) }) -test_that("time_pipe stores timings in a data frame", { +test_that("timings are stored in a log", { data.frame(x = 1:3) |> dplyr::mutate(y = x * 2) |> - time_pipe("step 1", console = FALSE, log = "times") |> + time_pipe("step1", console = FALSE, log = "log1") |> dplyr::mutate(z = y / 2) |> - time_pipe("step 2", console = FALSE, log = "times") - - expect_true(exists("times", envir = .pipetime_env)) + time_pipe("step2", console = FALSE, log = "log1") - # Load the stored data frame - stored <- get_log("times") + stored <- get_log("log1") expect_s3_class(stored, "data.frame") expect_equal(nrow(stored), 2) - expect_equal(stored$label, c("step 1", "step 2")) + expect_equal(stored$label, c("step1", "step2")) - # Remove the stored data frame - rm_log("times") - expect_false(exists("times", envir = .pipetime_env)) + rm_log("log1") + expect_false(exists("log1", envir = .pipetime_env)) }) - -test_that("time_pipe time is as expected", { +test_that("durations reflect elapsed time", { data.frame(x = 1:3) |> - time_pipe( - "pre-sleep", - unit = "secs", - log = "times", - console = FALSE - ) |> + time_pipe("pre", unit = "secs", log = "log2", console = FALSE) |> dplyr::mutate(result = Sys.sleep(0.5)) |> - time_pipe( - "post-sleep", - unit = "secs", - log = "times", - console = FALSE - ) - times <- get_log("times") - pre_time <- times$duration[1] - post_time <- times$duration[2] + time_pipe("post", unit = "secs", log = "log2", console = FALSE) + + times <- get_log("log2") + expect_true(times$duration[2] >= 0.5) + expect_true(times$duration[1] < 0.5) + + rm_log("log2") +}) + +test_that("multiple logs can be used independently", { + df <- data.frame(x = 1:3) + df |> time_pipe("a1", log = "loga", console = FALSE) + df |> time_pipe("b1", log = "logb", console = FALSE) + + logs <- get_log(NULL) # all logs + expect_named(logs, c("loga", "logb")) + expect_equal(nrow(logs$loga), 1) + expect_equal(nrow(logs$logb), 1) - expect_true(post_time >= 0.5) - expect_true(pre_time < 0.5) - rm_log("times") + rm_log(NULL, force = TRUE) # clear all + expect_length(get_log(NULL), 0) }) diff --git a/vignettes/timing_R_pipelines.Rmd b/vignettes/timing_R_pipelines.Rmd new file mode 100644 index 0000000..8026599 --- /dev/null +++ b/vignettes/timing_R_pipelines.Rmd @@ -0,0 +1,125 @@ +--- +title: "Timing R Pipelines" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{timing_R_pipelines} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +library(pipetime) +library(dplyr) +library(stringr) +library(ggplot2) +``` + +# Overview +`pipetime` enables **inline** timing of R pipelines (`|>`), helping identify performance bottlenecks and compare different approaches without disrupting your workflow. + +We illustrate this with a text processing example, comparing base R string functions against the optimized `stringr` package for common data cleaning tasks. + +- **Workflow A** 🐢 : Uses base R string functions (`gsub`, `substr`, `grepl`). + +- **Workflow B** 🚀: Uses `stringr`'s optimised functions. + +## Example Data +```{r} +set.seed(123) +make_str <- function(n) paste(sample(letters, n, TRUE), collapse = "") + +text_data <- data.frame( + id = 1:1e5, + email = paste0( + sapply(sample(5:15, 1e5, TRUE), make_str), + sample(c("@gmail.com", "@yahoo.com", "@hotmail.com"), 1e5, TRUE) + ), + phone = paste0( + "(", + sample(100:999, 1e5, TRUE), + ") ", + sample(100:999, 1e5, TRUE), + "-", + sample(1000:9999, 1e5, TRUE) + ), + text = sapply(sample(20:100, 1e5, TRUE), make_str) +) +head(text_data, n = 3) +``` + +## Timing Workflows +We use the `log` argument so each workflow stores its timings separately. + +```{r} +library(dplyr) +library(pipetime) +options(pipetime.console = FALSE) +# Workflow A: Base R +wf_A <- text_data |> + mutate( + domain = sub(".*@", "", email), + clean_phone = gsub("[^0-9]", "", phone), + word_count = lengths(strsplit(text, " ")) + ) |> + time_pipe("extract & clean", log = "base") |> + filter(grepl("^[a-m]", text)) |> + time_pipe("filter", log = "base") |> + mutate( + text_upper = toupper(text), + truncated = substr(text, 1, 50) + ) |> + time_pipe("transform", log = "base") + +# Workflow B: stringr (optimized) +wf_B <- text_data |> + mutate( + domain = str_extract(email, "(?<=@).*"), + clean_phone = str_remove_all(phone, "[^0-9]"), + word_count = str_count(text, "\\S+") + ) |> + time_pipe("extract & clean", log = "stringr") |> + filter(str_detect(text, "^[a-m]")) |> + time_pipe("filter", log = "stringr") |> + mutate( + text_upper = str_to_upper(text), + truncated = str_sub(text, 1, 50) + ) |> + time_pipe("transform", log = "stringr") + +``` + +# Results +```{r, dpi = 500} +# Collect both logs +logs <- get_log() |> + bind_rows(.id = "workflow") |> + group_by(workflow) |> + # Add a starting point + group_modify(~ add_row(.x, duration = 0, label = "start", .before = 1)) |> + mutate(step = factor(row_number())) + +library(ggplot2) +logs |> + ggplot( + aes( + x = step, + y = duration, + colour = workflow, + group = workflow + ) + ) + + geom_line(linewidth = 1) + + geom_point(size = 3) + + geom_text(aes(label = label), vjust = -0.7, size = 3.5, show.legend = FALSE) + + labs( + x = "Step", + y = "Cumulative time (sec)", + title = "Base R vs stringr", + colour = "Workflow" + ) + + theme_classic() +``` \ No newline at end of file diff --git a/vignettes/timing_operations_in_pipelines.Rmd b/vignettes/why_pipetime.Rmd similarity index 65% rename from vignettes/timing_operations_in_pipelines.Rmd rename to vignettes/why_pipetime.Rmd index 510d2f1..2da8c20 100644 --- a/vignettes/timing_operations_in_pipelines.Rmd +++ b/vignettes/why_pipetime.Rmd @@ -1,8 +1,8 @@ --- -title: "Timing Operations in R Pipelines" +title: "Why pipetime?" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{timing_operations_in_pipelines} + %\VignetteIndexEntry{why_pipetime} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -21,14 +21,11 @@ library(pipetime) library(dplyr) ``` -# Motivation - -R pipelines (`|>`) allow chaining operations in a readable, sequential way. Existing timing tools (e.g. `system.time()`, `tictoc`) do not integrate naturally with pipelines and tidy workflows. - -# Demonstration +R pipelines (`|>`) allow chaining operations in a readable, sequential way. Existing timing tools (e.g. `system.time()`, `tictoc`) do not integrate naturally with pipelines and tidy workflows. `pipetime` solves this by letting you measure time inline, without interrupting the pipeline. +# Examples ```{r} -complex_fn <- function(x) { +slow_op <- function(x) { Sys.sleep(0.1) # Simulate a time-consuming operation x^2 } @@ -37,19 +34,19 @@ complex_fn <- function(x) { ## `system.time()` ```{r, error=TRUE} -# Must wrap entire pipeline to record the time, breaking the flow +# Must wrap the entire pipeline, breaking the flow the_time <- system.time({ df <- data.frame(x = 1:3) |> - mutate(y = complex_fn(x)) |> + mutate(y = slow_op(x)) |> summarise(mean_y = mean(y)) }) the_time df -# Doesn't return the result of the pipeline, so will give an error +# system.time() cannot be inserted inline in a pipeline: data.frame(x = 1:3) |> - mutate(y = complex_fn(x)) |> - system_time() |> + mutate(y = slow_op(x)) |> + # system.time() would break the pipeline here summarise(mean_y = mean(y)) ``` @@ -58,10 +55,10 @@ data.frame(x = 1:3) |> ```{r} library(tictoc) -# Manual start/stop, not inline +# Requires manual start/stop tic("total pipeline") df <- data.frame(x = 1:3) |> - mutate(y = complex_fn(x)) |> + mutate(y = slow_op(x)) |> summarise(mean_y = mean(y)) toc() df @@ -70,18 +67,19 @@ df ## `time_pipe` ```{r} -# Inline timing checkpoints, keeps pipeline flow +# Inline timing checkpoints, pipeline stays intact data.frame(x = 1:3) |> - mutate(y = complex_fn(x)) |> + mutate(y = slow_op(x)) |> time_pipe("after mutate") |> summarise(mean_y = mean(y)) |> time_pipe("total pipeline") + ``` # Why `pipetime`? - Works directly inside pipelines. -- Supports multiple calls within the pipeline. +- Supports multiple checkpoints. -- Records timing operations in `.pipetime_env`. +- Prints or logs timings in `.pipetime_env` (see `?get_log`). \ No newline at end of file