--- title: "Getting Started with memtoc" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with memtoc} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ## Introduction memtoc provides simple start/stop memory tracking for R, inspired by the [tictoc](https://github.com/jabiru/tictoc) package for timing. Wrap any code block with `tic_mem()` and `toc_mem()` to measure RAM usage. ```{r setup} library(memtoc) ``` ## Basic Usage The simplest use case is tracking memory for a single operation: ```{r basic} tic_mem("load data") data <- read.csv("large_file.csv") toc_mem() #> ✔ load data: 142.3 MB peak | 142.3 MB current | 1.24 sec | 2 samples ``` The output shows: - **Peak memory**: Maximum RSS (Resident Set Size) during the operation - **Current memory**: RSS at the end of the operation - **Elapsed time**: Wall-clock time - **Samples**: Number of memory measurements taken ## Background Polling By default, memtoc spawns a background process that continuously samples memory. The reported peak is the maximum observed sample. Short-lived allocations between samples can be missed: ```{r polling} tic_mem("matrix operations", interval = 0.5) # Sample every 0.5 seconds # Create a large temporary matrix x <- matrix(rnorm(1e8), ncol = 1000) # ~800 MB y <- colMeans(x) # x can be garbage collected rm(x) gc() result <- toc_mem() #> ✔ matrix operations: 812.4 MB peak | 45.2 MB current | 3.21 sec | 7 samples ``` Without background polling, you would only see the final memory (45.2 MB), missing the 800 MB peak. Access the full trajectory with `result$trajectory`. For very quick operations, disable polling to avoid startup overhead: ```{r snapshot} tic_mem("quick op", interval = NULL) # Snapshot mode y <- 1:100 toc_mem() ``` ## Nested Tracking Track an entire pipeline while also measuring individual steps: ```{r nested} tic_mem("full pipeline") tic_mem("step 1: load") data <- read.csv("data.csv") toc_mem() #> ✔ step 1: load: 50.2 MB peak | 50.2 MB current | 1.2 sec tic_mem("step 2: transform") features <- transform(data) toc_mem() #> ✔ step 2: transform: 125.8 MB peak | 98.3 MB current | 2.4 sec tic_mem("step 3: model") model <- train(features) toc_mem() #> ✔ step 3: model: 512.1 MB peak | 201.5 MB current | 45.2 sec toc_mem() #> ✔ full pipeline: 512.1 MB peak | 201.5 MB current | 48.8 sec ``` ## Logging Results Collect results for later analysis: ```{r logging} mem_clearlog() for (i in 1:10) { tic_mem(paste("iteration", i)) # ... do work ... toc_mem(log = TRUE, quiet = TRUE) } # Get all results as a data frame results <- mem_log() summary(results$mem_peak) ``` ## Parallel Worker Monitoring When using the `future` package for parallel processing, memtoc can monitor memory across all workers: ```{r parallel} library(future) library(future.apply) # Set up parallel workers plan(multisession, workers = 4) # Check that workers are detected mem_parallel_info() #> ── Parallel Backend Info #> • Main process PID: 12345 #> • Current plan: multisession #> • Workers configured: 4 # Monitor parallel job tic_mem("parallel computation", workers = "auto") result <- future_lapply(1:100, function(i) { x <- rnorm(1e6) mean(x) }, future.seed = TRUE) mem_result <- toc_mem() #> ✔ parallel computation: 1.2 GB peak | 245 MB current | 5.4 sec | 4 workers # View per-worker breakdown mem_result$worker_stats # Clean up plan(sequential) ``` Worker options: - `workers = "auto"`: Auto-detect future workers (default) - `workers = "none"`: Only monitor main process - `workers = "children"`: Monitor main process and child processes - `workers = c(pid1, pid2)`: Explicit PID list ## System Memory Warnings memtoc warns you when system RAM is running low: ```{r warnings} tic_mem("memory intensive") # ... allocate lots of memory ... toc_mem() #> ✔ memory intensive: 12.4 GB peak | 11.2 GB current | 45.2 sec #> ⚠ System RAM high: 87.3% used ``` Warnings appear at 80% usage; critical alerts at 95%. ## Crash Recovery Checkpoints are stored in R's session-specific temporary directory. Within a session, list available checkpoints or recover the outer block by PID. After a restart, use `mem_recover(path = ...)` with the actual surviving checkpoint path from the previous session. If the temporary directory was removed, the samples cannot be recovered. Normal completion removes checkpoints. ```{r recovery} # List checkpoints in this R session mem_recover() #> ℹ Found 1 recovery file: #> • PID 12345: 15.2 KB, 152 samples # Recover the data recovered <- mem_recover(pid = 12345) head(recovered) ``` ## Diagnostics If background polling isn't working, run diagnostics: ```{r diagnostics} mem_capabilities() #> memory_queries background_polling #> TRUE TRUE # Detailed troubleshooting mem_diagnose() ``` ## Tips 1. **Use labels**: Always pass a message to `tic_mem()` for easier tracking 2. **Adjust interval**: Use shorter intervals (0.1-0.5s) for fast operations, longer intervals (1-5s) for long-running jobs 3. **Disable polling for quick ops**: Use `interval = NULL` for sub-second operations 4. **Monitor workers**: Set `workers = "auto"` when using `future` for parallelism 5. **Log results**: Use `log = TRUE` when running benchmarks or comparisons