1% Generated by roxygen2: do not edit by hand 2% Please edit documentation in R/bind-cache.R 3\name{bindCache} 4\alias{bindCache} 5\title{Add caching with reactivity to an object} 6\usage{ 7bindCache(x, ..., cache = "app") 8} 9\arguments{ 10\item{x}{The object to add caching to.} 11 12\item{...}{One or more expressions to use in the caching key.} 13 14\item{cache}{The scope of the cache, or a cache object. This can be \code{"app"} 15(the default), \code{"session"}, or a cache object like a 16\code{\link[cachem:cache_disk]{cachem::cache_disk()}}. See the Cache Scoping section for more information.} 17} 18\description{ 19\code{bindCache()} adds caching \code{\link[=reactive]{reactive()}} expressions and \verb{render*} functions 20(like \code{\link[=renderText]{renderText()}}, \code{\link[=renderTable]{renderTable()}}, ...). 21 22Ordinary \code{\link[=reactive]{reactive()}} expressions automatically cache their \emph{most recent} 23value, which helps to avoid redundant computation in downstream reactives. 24\code{bindCache()} will cache all previous values (as long as they fit in the 25cache) and they can be shared across user sessions. This allows 26\code{bindCache()} to dramatically improve performance when used correctly. 27} 28\details{ 29\code{bindCache()} requires one or more expressions that are used to generate a 30\strong{cache key}, which is used to determine if a computation has occurred 31before and hence can be retrieved from the cache. If you're familiar with the 32concept of memoizing pure functions (e.g., the \pkg{memoise} package), you 33can think of the cache key as the input(s) to a pure function. As such, one 34should take care to make sure the use of \code{bindCache()} is \emph{pure} in the same 35sense, namely: 36\enumerate{ 37\item For a given key, the return value is always the same. 38\item Evaluation has no side-effects. 39} 40 41In the example here, the \code{bindCache()} key consists of \code{input$x} and 42\code{input$y} combined, and the value is \code{input$x * input$y}. In this simple 43example, for any given key, there is only one possible returned value.\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\% 44 bindCache(input$x, input$y) 45}\if{html}{\out{</div>}} 46 47The largest performance improvements occur when the cache key is fast to 48compute and the reactive expression is slow to compute. To see if the value 49should be computed, a cached reactive evaluates the key, and then serializes 50and hashes the result. If the resulting hashed key is in the cache, then the 51cached reactive simply retrieves the previously calculated value and returns 52it; if not, then the value is computed and the result is stored in the cache 53before being returned. 54 55To compute the cache key, \code{bindCache()} hashes the contents of \code{...}, so it's 56best to avoid including large objects in a cache key since that can result in 57slow hashing. It's also best to avoid reference objects like environments and 58R6 objects, since the serialization of these objects may not capture relevant 59changes. 60 61If you want to use a large object as part of a cache key, it may make sense 62to do some sort of reduction on the data that still captures information 63about whether a value can be retrieved from the cache. For example, if you 64have a large data set with timestamps, it might make sense to extract the 65most recent timestamp and return that. Then, instead of hashing the entire 66data object, the cached reactive only needs to hash the timestamp.\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ compute(bigdata()) \} \%>\% 67 bindCache(\{ extract_most_recent_time(bigdata()) \}) 68}\if{html}{\out{</div>}} 69 70For computations that are very slow, it often makes sense to pair 71\code{\link[=bindCache]{bindCache()}} with \code{\link[=bindEvent]{bindEvent()}} so that no computation is performed until 72the user explicitly requests it (for more, see the Details section of 73\code{\link[=bindEvent]{bindEvent()}}). 74} 75\section{Cache keys and reactivity}{ 76 77 78Because the \strong{value} expression (from the original \code{\link[=reactive]{reactive()}}) is 79cached, it is not necessarily re-executed when someone retrieves a value, 80and therefore it can't be used to decide what objects to take reactive 81dependencies on. Instead, the \strong{key} is used to figure out which objects 82to take reactive dependencies on. In short, the key expression is reactive, 83and value expression is no longer reactive. 84 85Here's an example of what not to do: if the key is \code{input$x} and the value 86expression is from \code{reactive({input$x + input$y})}, then the resulting 87cached reactive will only take a reactive dependency on \code{input$x} -- it 88won't recompute \code{{input$x + input$y}} when just \code{input$y} changes. 89Moreover, the cache won't use \code{input$y} as part of the key, and so it could 90return incorrect values in the future when it retrieves values from the 91cache. (See the examples below for an example of this.) 92 93A better cache key would be something like \verb{input$x, input$y}. This does 94two things: it ensures that a reactive dependency is taken on both 95\code{input$x} and \code{input$y}, and it also makes sure that both values are 96represented in the cache key. 97 98In general, \code{key} should use the same reactive inputs as \code{value}, but the 99computation should be simpler. If there are other (non-reactive) values 100that are consumed, such as external data sources, they should be used in 101the \code{key} as well. Note that if the \code{key} is large, it can make sense to do 102some sort of reduction on it so that the serialization and hashing of the 103cache key is not too expensive. 104 105Remember that the key is \emph{reactive}, so it is not re-executed every single 106time that someone accesses the cached reactive. It is only re-executed if 107it has been invalidated by one of the reactives it depends on. For 108example, suppose we have this cached reactive:\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\% 109 bindCache(input$x, input$y) 110}\if{html}{\out{</div>}} 111 112In this case, the key expression is essentially \code{reactive(list(input$x, input$y))} (there's a bit more to it, but that's a good enough 113approximation). The first time \code{r()} is called, it executes the key, then 114fails to find it in the cache, so it executes the value expression, \code{{ input$x + input$y }}. If \code{r()} is called again, then it does not need to 115re-execute the key expression, because it has not been invalidated via a 116change to \code{input$x} or \code{input$y}; it simply returns the previous value. 117However, if \code{input$x} or \code{input$y} changes, then the reactive expression will 118be invalidated, and the next time that someone calls \code{r()}, the key 119expression will need to be re-executed. 120 121Note that if the cached reactive is passed to \code{\link[=bindEvent]{bindEvent()}}, then the key 122expression will no longer be reactive; instead, the event expression will be 123reactive. 124} 125 126\section{Cache scope}{ 127 128 129By default, when \code{bindCache()} is used, it is scoped to the running 130application. That means that it shares a cache with all user sessions 131connected to the application (within the R process). This is done with the 132\code{cache} parameter's default value, \code{"app"}. 133 134With an app-level cache scope, one user can benefit from the work done for 135another user's session. In most cases, this is the best way to get 136performance improvements from caching. However, in some cases, this could 137leak information between sessions. For example, if the cache key does not 138fully encompass the inputs used by the value, then data could leak between 139the sessions. Or if a user sees that a cached reactive returns its value 140very quickly, they may be able to infer that someone else has already used 141it with the same values. 142 143It is also possible to scope the cache to the session, with 144\code{cache="session"}. This removes the risk of information leaking between 145sessions, but then one session cannot benefit from computations performed in 146another session. 147 148It is possible to pass in caching objects directly to 149\code{bindCache()}. This can be useful if, for example, you want to use a 150particular type of cache with specific cached reactives, or if you want to 151use a \code{\link[cachem:cache_disk]{cachem::cache_disk()}} that is shared across multiple processes and 152persists beyond the current R session. 153 154To use different settings for an application-scoped cache, you can call 155\code{\link[=shinyOptions]{shinyOptions()}} at the top of your app.R, server.R, or 156global.R. For example, this will create a cache with 500 MB of space 157instead of the default 200 MB:\preformatted{shinyOptions(cache = cachem::cache_mem(max_size = 500e6)) 158} 159 160To use different settings for a session-scoped cache, you can set 161\code{self$cache} at the top of your server function. By default, it will create 162a 200 MB memory cache for each session, but you can replace it with 163something different. To use the session-scoped cache, you must also call 164\code{bindCache()} with \code{cache="session"}. This will create a 100 MB cache for 165the session:\preformatted{function(input, output, session) \{ 166 session$cache <- cachem::cache_mem(max_size = 100e6) 167 ... 168\} 169} 170 171If you want to use a cache that is shared across multiple R processes, you 172can use a \code{\link[cachem:cache_disk]{cachem::cache_disk()}}. You can create a application-level shared 173cache by putting this at the top of your app.R, server.R, or global.R:\preformatted{shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache")) 174} 175 176This will create a subdirectory in your system temp directory named 177\code{myapp-cache} (replace \code{myapp-cache} with a unique name of 178your choosing). On most platforms, this directory will be removed when 179your system reboots. This cache will persist across multiple starts and 180stops of the R process, as long as you do not reboot. 181 182To have the cache persist even across multiple reboots, you can create the 183cache in a location outside of the temp directory. For example, it could 184be a subdirectory of the application:\preformatted{shinyOptions(cache = cachem::cache_disk("./myapp-cache")) 185} 186 187In this case, resetting the cache will have to be done manually, by deleting 188the directory. 189 190You can also scope a cache to just one item, or selected items. To do that, 191create a \code{\link[cachem:cache_mem]{cachem::cache_mem()}} or \code{\link[cachem:cache_disk]{cachem::cache_disk()}}, and pass it 192as the \code{cache} argument of \code{bindCache()}. 193} 194 195\section{Computing cache keys}{ 196 197 198The actual cache key that is used internally takes value from evaluating 199the key expression(s) (from the \code{...} arguments) and combines it with the 200(unevaluated) value expression. 201 202This means that if there are two cached reactives which have the same 203result from evaluating the key, but different value expressions, then they 204will not need to worry about collisions. 205 206However, if two cached reactives have identical key and value expressions 207expressions, they will share the cached values. This is useful when using 208\code{cache="app"}: there may be multiple user sessions which create separate 209cached reactive objects (because they are created from the same code in the 210server function, but the server function is executed once for each user 211session), and those cached reactive objects across sessions can share 212values in the cache. 213} 214 215\section{Async with cached reactives}{ 216 217 218With a cached reactive expression, the key and/or value expression can be 219\emph{asynchronous}. In other words, they can be promises --- not regular R 220promises, but rather objects provided by the 221\href{https://rstudio.github.io/promises/}{\pkg{promises}} package, which 222are similar to promises in JavaScript. (See \code{\link[promises:promise]{promises::promise()}} for more 223information.) You can also use \code{\link[future:future]{future::future()}} objects to run code in a 224separate process or even on a remote machine. 225 226If the value returns a promise, then anything that consumes the cached 227reactive must expect it to return a promise. 228 229Similarly, if the key is a promise (in other words, if it is asynchronous), 230then the entire cached reactive must be asynchronous, since the key must be 231computed asynchronously before it knows whether to compute the value or the 232value is retrieved from the cache. Anything that consumes the cached 233reactive must therefore expect it to return a promise. 234} 235 236\section{Developing render functions for caching}{ 237 238 239If you've implemented your own \verb{render*()} function, it may just work with 240\code{bindCache()}, but it is possible that you will need to make some 241modifications. These modifications involve helping \code{bindCache()} avoid 242cache collisions, dealing with internal state that may be set by the, 243\code{render} function, and modifying the data as it goes in and comes out of 244the cache. 245 246You may need to provide a \code{cacheHint} to \code{\link[=createRenderFunction]{createRenderFunction()}} (or 247\code{htmlwidgets::shinyRenderWidget()}, if you've authored an htmlwidget) in 248order for \code{bindCache()} to correctly compute a cache key. 249 250The potential problem is a cache collision. Consider the following:\preformatted{output$x1 <- renderText(\{ input$x \}) \%>\% bindCache(input$x) 251output$x2 <- renderText(\{ input$x * 2 \}) \%>\% bindCache(input$x) 252} 253 254Both \code{output$x1} and \code{output$x2} use \code{input$x} as part of their cache key, 255but if it were the only thing used in the cache key, then the two outputs 256would have a cache collision, and they would have the same output. To avoid 257this, a \emph{cache hint} is automatically added when \code{\link[=renderText]{renderText()}} calls 258\code{\link[=createRenderFunction]{createRenderFunction()}}. The cache hint is used as part of the actual 259cache key, in addition to the one passed to \code{bindCache()} by the user. The 260cache hint can be viewed by calling the internal Shiny function 261\code{extractCacheHint()}:\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- renderText(\{ input$x \}) 262shiny:::extractCacheHint(r) 263}\if{html}{\out{</div>}} 264 265This returns a nested list containing an item, \verb{$origUserFunc$body}, which 266in this case is the expression which was passed to \code{renderText()}: 267\code{{ input$x }}. This (quoted) expression is mixed into the actual cache 268key, and it is how \code{output$x1} does not have collisions with \code{output$x2}. 269 270For most developers of render functions, nothing extra needs to be done; 271the automatic inference of the cache hint is sufficient. Again, you can 272check it by calling \code{shiny:::extractCacheHint()}, and by testing the 273render function for cache collisions in a real application. 274 275In some cases, however, the automatic cache hint inference is not 276sufficient, and it is necessary to provide a cache hint. This is true 277for \code{renderPrint()}. Unlike \code{renderText()}, it wraps the user-provided 278expression in another function, before passing it to \code{\link[=createRenderFunction]{createRenderFunction()}} 279(instead of \code{\link[=createRenderFunction]{createRenderFunction()}}). Because the user code is wrapped in 280another function, \code{createRenderFunction()} is not able to automatically 281extract the user-provided code and use it in the cache key. Instead, 282\code{renderPrint} calls \code{createRenderFunction()}, it explicitly passes along a 283\code{cacheHint}, which includes a label and the original user expression. 284 285In general, if you need to provide a \code{cacheHint}, it is best practice to 286provide a \code{label} id, the user's \code{expr}, as well as any other arguments 287that may influence the final value. 288 289For \pkg{htmlwidgets}, it will try to automatically infer a cache hint; 290again, you can inspect the cache hint with \code{shiny:::extractCacheHint()} and 291also test it in an application. If you do need to explicitly provide a 292cache hint, pass it to \code{shinyRenderWidget}. For example:\preformatted{renderMyWidget <- function(expr) \{ 293 q <- rlang::enquo0(expr) 294 295 htmlwidgets::shinyRenderWidget( 296 q, 297 myWidgetOutput, 298 quoted = TRUE, 299 cacheHint = list(label = "myWidget", userQuo = q) 300 ) 301\} 302} 303 304If your \code{render} function sets any internal state, you may find it useful 305in your call to \code{\link[=createRenderFunction]{createRenderFunction()}} to use 306the \code{cacheWriteHook} and/or \code{cacheReadHook} parameters. These hooks are 307functions that run just before the object is stored in the cache, and just 308after the object is retrieved from the cache. They can modify the data 309that is stored and retrieved; this can be useful if extra information needs 310to be stored in the cache. They can also be used to modify the state of the 311application; for example, it can call \code{\link[=createWebDependency]{createWebDependency()}} to make 312JS/CSS resources available if the cached object is loaded in a different R 313process. (See the source of \code{htmlwidgets::shinyRenderWidget} for an example 314of this.) 315} 316 317\section{Uncacheable objects}{ 318 319 320Some render functions cannot be cached, typically because they have side 321effects or modify some external state, and they must re-execute each time 322in order to work properly. 323 324For developers of such code, they should call \code{\link[=createRenderFunction]{createRenderFunction()}} (or 325\code{\link[=markRenderFunction]{markRenderFunction()}}) with \code{cacheHint = FALSE}. 326} 327 328\section{Caching with \code{renderPlot()}}{ 329 330 331When \code{bindCache()} is used with \code{renderPlot()}, the \code{height} and \code{width} 332passed to the original \code{renderPlot()} are ignored. They are superseded by 333\code{sizePolicy} argument passed to `bindCache. The default is:\preformatted{sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2) 334} 335 336\code{sizePolicy} must be a function that takes a two-element numeric vector as 337input, representing the width and height of the \verb{<img>} element in the 338browser window, and it must return a two-element numeric vector, representing 339the pixel dimensions of the plot to generate. The purpose is to round the 340actual pixel dimensions from the browser to some other dimensions, so that 341this will not generate and cache images of every possible pixel dimension. 342See \code{\link[=sizeGrowthRatio]{sizeGrowthRatio()}} for more information on the default sizing policy. 343} 344 345\examples{ 346\dontrun{ 347rc <- bindCache( 348 x = reactive({ 349 Sys.sleep(2) # Pretend this is expensive 350 input$x * 100 351 }), 352 input$x 353) 354 355# Can make it prettier with the \%>\% operator 356library(magrittr) 357 358rc <- reactive({ 359 Sys.sleep(2) 360 input$x * 100 361}) \%>\% 362 bindCache(input$x) 363 364} 365 366## Only run app examples in interactive R sessions 367if (interactive()) { 368 369# Basic example 370shinyApp( 371 ui = fluidPage( 372 sliderInput("x", "x", 1, 10, 5), 373 sliderInput("y", "y", 1, 10, 5), 374 div("x * y: "), 375 verbatimTextOutput("txt") 376 ), 377 server = function(input, output) { 378 r <- reactive({ 379 # The value expression is an _expensive_ computation 380 message("Doing expensive computation...") 381 Sys.sleep(2) 382 input$x * input$y 383 }) \%>\% 384 bindCache(input$x, input$y) 385 386 output$txt <- renderText(r()) 387 } 388) 389 390 391# Caching renderText 392shinyApp( 393 ui = fluidPage( 394 sliderInput("x", "x", 1, 10, 5), 395 sliderInput("y", "y", 1, 10, 5), 396 div("x * y: "), 397 verbatimTextOutput("txt") 398 ), 399 server = function(input, output) { 400 output$txt <- renderText({ 401 message("Doing expensive computation...") 402 Sys.sleep(2) 403 input$x * input$y 404 }) \%>\% 405 bindCache(input$x, input$y) 406 } 407) 408 409 410# Demo of using events and caching with an actionButton 411shinyApp( 412 ui = fluidPage( 413 sliderInput("x", "x", 1, 10, 5), 414 sliderInput("y", "y", 1, 10, 5), 415 actionButton("go", "Go"), 416 div("x * y: "), 417 verbatimTextOutput("txt") 418 ), 419 server = function(input, output) { 420 r <- reactive({ 421 message("Doing expensive computation...") 422 Sys.sleep(2) 423 input$x * input$y 424 }) \%>\% 425 bindCache(input$x, input$y) \%>\% 426 bindEvent(input$go) 427 # The cached, eventified reactive takes a reactive dependency on 428 # input$go, but doesn't use it for the cache key. It uses input$x and 429 # input$y for the cache key, but doesn't take a reactive depdency on 430 # them, because the reactive dependency is superseded by addEvent(). 431 432 output$txt <- renderText(r()) 433 } 434) 435 436} 437 438} 439\seealso{ 440\code{\link[=bindEvent]{bindEvent()}}, \code{\link[=renderCachedPlot]{renderCachedPlot()}} for caching plots. 441} 442