| Title: | 'Tictoc'-Style Memory Usage Tracking |
|---|---|
| Description: | Provides simple start/stop memory tracking functions tic_mem() and toc_mem() that can be nested, inspired by the 'tictoc' package. Track RAM usage during code execution with support for logging, custom messages, nested tracking blocks, and parallel worker monitoring. Features continuous background polling to estimate peak memory usage across main process and workers. Integrates with the 'future' package ecosystem for automatic worker detection. Designed for monitoring memory consumption in parallel workflows. |
| Authors: | Juan Ocampo [aut, cre] (ORCID: <https://orcid.org/0000-0002-9353-7581>) |
| Maintainer: | Juan Ocampo <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.1 |
| Built: | 2026-09-26 23:10:00 UTC |
| Source: | https://github.com/cran/memtoc |
Tests which features are available on the current system. This is useful for understanding why certain features might be disabled.
mem_capabilities()mem_capabilities()
A named logical vector with elements:
memory_queries |
Can query process memory via ps package |
background_polling |
Can spawn background processes via callr |
mem_capabilities()mem_capabilities()
Removes all entries from the tracking stack. This is useful if an error
occurred before toc_mem() could be called, leaving orphaned entries
on the stack.
mem_clear()mem_clear()
Also stops any running background monitors associated with orphaned entries.
Invisibly returns NULL.
tic_mem("will be cleared") mem_clear() # Stack is now emptytic_mem("will be cleared") mem_clear() # Stack is now empty
Removes all entries from the memtoc log. This does not affect the tracking stack (active tic_mem/toc_mem blocks).
mem_clearlog()mem_clearlog()
Invisibly returns NULL.
mem_log() to retrieve the log before clearing
mem_clearlog() tic_mem("example", interval = NULL, workers = "none") toc_mem(log = TRUE, quiet = TRUE) nrow(mem_log()) mem_clearlog() nrow(mem_log())mem_clearlog() tic_mem("example", interval = NULL, workers = "none") toc_mem(log = TRUE, quiet = TRUE) nrow(mem_log()) mem_clearlog() nrow(mem_log())
Runs detailed diagnostics to identify issues with background process
spawning. Useful for troubleshooting when mem_capabilities() shows
background_polling = FALSE.
mem_diagnose()mem_diagnose()
Invisibly returns a list with diagnostic results
mem_diagnose()mem_diagnose()
Returns a data frame containing all logged memory tracking results.
Results are added to the log when toc_mem(log = TRUE) is called.
mem_log(format = c("data.frame", "list"))mem_log(format = c("data.frame", "list"))
format |
Character string specifying the output format.
|
A data frame (default) or list containing logged results. The data frame has columns:
Label from tic_mem(), or NA if none provided
Memory (RSS) in bytes at start
Memory (RSS) in bytes at end
Peak memory in bytes
Change in memory (bytes)
Elapsed time in seconds
When tic_mem() was called
When toc_mem() was called
mem_clearlog() to clear the log, toc_mem() with log = TRUE
mem_clearlog() tic_mem("step 1", interval = NULL, workers = "none") x <- numeric(100) toc_mem(log = TRUE, quiet = TRUE) tic_mem("step 2", interval = NULL, workers = "none") y <- sum(x) toc_mem(log = TRUE, quiet = TRUE) mem_log() mem_clearlog()mem_clearlog() tic_mem("step 1", interval = NULL, workers = "none") x <- numeric(100) toc_mem(log = TRUE, quiet = TRUE) tic_mem("step 2", interval = NULL, workers = "none") y <- sum(x) toc_mem(log = TRUE, quiet = TRUE) mem_log() mem_clearlog()
Returns diagnostic information about the detected parallel backend and any workers that can be monitored.
mem_parallel_info()mem_parallel_info()
A list with parallel backend information
info <- mem_parallel_info() info$main_pid info$worker_pidsinfo <- mem_parallel_info() info$main_pid info$worker_pids
Displays the memory tracking log in a human-readable format, similar to how tictoc's tic.log() output can be printed with writeLines().
mem_print_log()mem_print_log()
Invisibly returns a character vector of formatted log lines.
mem_clearlog() tic_mem("step 1", interval = NULL, workers = "none") x <- numeric(100) toc_mem(log = TRUE, quiet = TRUE) tic_mem("step 2", interval = NULL, workers = "none") y <- sum(x) toc_mem(log = TRUE, quiet = TRUE) mem_print_log() mem_clearlog()mem_clearlog() tic_mem("step 1", interval = NULL, workers = "none") x <- numeric(100) toc_mem(log = TRUE, quiet = TRUE) tic_mem("step 2", interval = NULL, workers = "none") y <- sum(x) toc_mem(log = TRUE, quiet = TRUE) mem_print_log() mem_clearlog()
Attempts to recover memory samples from a previous session that crashed or was interrupted before toc_mem() was called. The monitor periodically saves checkpoints to disk, so some data may be recoverable.
mem_recover(pid = NULL, path = NULL)mem_recover(pid = NULL, path = NULL)
pid |
Process ID for a checkpoint in the current session's temporary directory. If NULL, lists available recovery files in that directory. |
path |
Direct path to a recovery file. Overrides pid if provided. |
Checkpoints are stored in the current R session's temporary directory.
After restarting R, use path to locate a surviving checkpoint in the
previous session's temporary directory; recovery is not guaranteed if
that directory has been removed. Normal completion removes checkpoints.
Nested blocks have separate files and can be recovered using path.
If pid or path is provided, returns a data frame of recovered samples or NULL if not found. If both are NULL, returns a list of available recovery files with their metadata.
mem_recover() # Recover a small example checkpoint from a temporary file. local({ path <- tempfile(fileext = ".rds") on.exit(unlink(path)) samples <- data.frame( timestamp = Sys.time(), pid = Sys.getpid(), rss = 1024^2 ) saveRDS(samples, path) recovered <- mem_recover(path = path) stopifnot(identical(recovered, samples)) recovered })mem_recover() # Recover a small example checkpoint from a temporary file. local({ path <- tempfile(fileext = ".rds") on.exit(unlink(path)) samples <- data.frame( timestamp = Sys.time(), pid = Sys.getpid(), rss = 1024^2 ) saveRDS(samples, path) recovered <- mem_recover(path = path) stopifnot(identical(recovered, samples)) recovered })
Print method for memtoc_result objects
## S3 method for class 'memtoc_result' print(x, ...)## S3 method for class 'memtoc_result' print(x, ...)
x |
A memtoc_result object |
... |
Additional arguments (ignored) |
Invisibly returns x
Begins a memory tracking block. Call toc_mem() to end the block and
see the results. Multiple calls to tic_mem() can be nested, and each
toc_mem() will match with the most recent unmatched tic_mem().
tic_mem(msg = NULL, quiet = TRUE, interval = 1, workers = "auto")tic_mem(msg = NULL, quiet = TRUE, interval = 1, workers = "auto")
msg |
Optional character string label for this tracking block.
This label is displayed in the output from |
quiet |
Logical. If |
interval |
Numeric. Polling interval in seconds for background
monitoring. Set to |
workers |
Worker specification for parallel monitoring:
|
When interval is set (default), a background R process is spawned to
sample memory usage. The reported peak is the maximum observed sample;
allocations between samples may be missed. Starting and running the
background process adds overhead.
For very short operations (under 1 second), consider using interval = NULL
to avoid the background process startup overhead (~200ms).
When using future for parallel processing, memtoc can automatically
detect and monitor worker processes. Set workers = "auto" to enable
this feature. The trajectory will include memory samples from all
workers, and the result will show aggregate statistics.
Invisibly returns the timestamp when tracking started.
toc_mem() to stop tracking, mem_log() to retrieve logged results,
mem_parallel_info() to check parallel backend status
# Track a small allocation using start and end snapshots. tic_mem("small allocation", interval = NULL, workers = "none") x <- numeric(1000) toc_mem() # Nested blocks are stopped in reverse order. tic_mem("outer", interval = NULL, workers = "none") tic_mem("inner", interval = NULL, workers = "none") y <- sum(x) toc_mem() toc_mem()# Track a small allocation using start and end snapshots. tic_mem("small allocation", interval = NULL, workers = "none") x <- numeric(1000) toc_mem() # Nested blocks are stopped in reverse order. tic_mem("outer", interval = NULL, workers = "none") tic_mem("inner", interval = NULL, workers = "none") y <- sum(x) toc_mem() toc_mem()
Ends a memory tracking block started by tic_mem() and reports the results.
By default, prints a summary message showing peak memory, current memory,
and elapsed time.
toc_mem(log = FALSE, quiet = FALSE)toc_mem(log = FALSE, quiet = FALSE)
log |
Logical. If |
quiet |
Logical. If |
Invisibly returns a memtoc_result object (a list) containing:
msg |
The label passed to |
mem_start |
Memory (RSS) in bytes at start (main process) |
mem_end |
Memory (RSS) in bytes at end (main process) |
mem_peak |
Peak memory during the interval (total across all processes) |
mem_change |
Change in memory (end - start) in bytes |
elapsed |
Elapsed time in seconds |
tic_timestamp |
POSIXct timestamp when tic_mem() was called |
toc_timestamp |
POSIXct timestamp when toc_mem() was called |
trajectory |
Data frame of memory samples (if background polling was used) |
n_samples |
Number of samples collected |
n_workers |
Number of worker processes monitored (0 if main process only) |
worker_stats |
Data frame with per-worker peak memory (if workers monitored) |
tic_mem() to start tracking, mem_log() to retrieve logged results
tic_mem("small allocation", interval = NULL, workers = "none") x <- numeric(1000) result <- toc_mem() result$elapsed result$mem_peak result$n_samples # Brief background polling; sample availability depends on startup time. tic_mem("polling", interval = 0.1, workers = "none") Sys.sleep(0.3) polled <- toc_mem() if (!is.null(polled$trajectory)) { head(polled$trajectory) }tic_mem("small allocation", interval = NULL, workers = "none") x <- numeric(1000) result <- toc_mem() result$elapsed result$mem_peak result$n_samples # Brief background polling; sample availability depends on startup time. tic_mem("polling", interval = 0.1, workers = "none") Sys.sleep(0.3) polled <- toc_mem() if (!is.null(polled$trajectory)) { head(polled$trajectory) }