<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/shiny-1-1-0-scaling-shiny-with-async/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://blog.rstudio.com/2018/06/26/shiny-1-1-0/"> RStudio Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>This is a significant release for <strong><a rel="nofollow" href="https://shiny.rstudio.com/" target="_blank">Shiny</a></strong>, with a major new feature that was nearly a year in the making: support for asynchronous operations!</p>
<p>Without this capability, when Shiny performs long-running calculations or tasks on behalf of one user, it stalls progress for all other Shiny users that are connected to the same process. Therefore, Shiny apps that feature long-running calculations or tasks have generally been deployed using many R processes, each serving a small number of users; this works, but is not the most efficient approach. Such applications now have an important new tool in the toolbox to improve performance under load.</p>
<p>Shiny async is implemented via integration with the <strong><a rel="nofollow" href="https://github.com/HenrikBengtsson/future" target="_blank">future</a></strong> and <strong><a rel="nofollow" href="https://rstudio.github.io/promises/" target="_blank">promises</a></strong> packages. These two packages are used together:</p>
<ol>
<li><strong>Use <code>future</code> to perform long-running operations in a worker process that runs in the background</strong>, leaving Shiny processes free to serve other users in the meantime. This yields much better responsiveness under load, and much more predictable latency.</li>
<li><strong>Use <code>promises</code> to handle the result of each long-running background operation back in the Shiny process</strong>, where additional processing can occur, such as further data manipulation, or displaying to the user via a reactive output.</li>
</ol>
<p>If your app has a small number of severe performance bottlenecks, you can use this technique to get massively better responsiveness under load. For example, if the <code>httr::GET</code> call in this server function takes 30 seconds to complete:</p>
<pre><code>server &lt;- function(input, output, session) {
  r &lt;- reactive({
    httr::GET(url) %>%
      httr::content(&quot;parsed&quot;)
  })

  output$plot &lt;- renderPlot({
    r() %>%
      ggplot(aes(speed, dist)) + geom_point()
  })
}
</code></pre>
<p>then the entire R process is stalled for those 30 seconds.</p>
<p>We can rewrite it asynchronously like this:</p>
<pre><code>library(promises)
library(future)
plan(multisession)

server &lt;- function(input, output, session) {
  r &lt;- reactive({
    future(httr::GET(url)) %...>%
      httr::content(&quot;parsed&quot;) %...>%
  })
  
  output$plot &lt;- renderPlot({
    r() %...>% {
      ggplot(., aes(speed, dist)) + geom_point()
    }
  })
}

</code></pre>
<p>Even if the <code>httr::GET(url)</code> takes 30 seconds, the <code>r</code> reactive executes almost instantly, and returns control to the caller. The code inside <code>future(...)</code> is executed in a different R process that runs in the background, and whenever its result becomes available (i.e. in 30 seconds), the right-hand side of <code>%...>%</code> will be executed with that result. (<code>%...>%</code> is called a “promise pipe”; it works similarly to a magrittr pipe that knows how to wait for and “unwrap” promises.)</p>
<p>If the original (synchronous) code appeared in a Shiny app, then during that 30 seconds, the R process is stuck dealing with the download and can’t respond to any requests being made by other users. But with the async version, the R process only needs to kick off the operation, and then is free to service other requests. This means other users will only have to wait milliseconds, not minutes, for the app to respond.</p>
<h3>Case study</h3>
<p>We’ve created a <a rel="nofollow" href="https://rstudio.github.io/promises/articles/casestudy.html" target="_blank">detailed case study</a> that walks through the async conversion of a realistic example app. This app processes low-level logging data from RStudio’s CRAN mirrors, to let us explore the heaviest downloaders for each day.</p>
<p><img alt="" src="https://i2.wp.com/rstudio.github.io/promises/articles/case-study-tab3.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>To load test this example app, we launched 50 sessions of simulated load, with a 5 second delay between each launch, and directed this traffic to a single R process. We then rewrote the app to use futures and promises, and reran the load test with this async version. (The tools we used to perform the load testing are not yet publicly available, but you can refer to <a rel="nofollow" href="https://www.rstudio.com/resources/videos/scaling-shiny/" target="_blank">Sean Lopp’s talk at rstudio::conf 2018</a> for a preview.)</p>
<p>Under these conditions, the finished async version displays significantly lower (mean) response times than the original. In the table below, “HTTP traffic” refers to requests that are made during page load time, and “reactive processing” refers to the time between the browser sending a reactive input value and the server returning updated reactive outputs.</p>

<table>
<thead>
<tr>
<th>Response type</th>
<th>Original</th>
<th>Async</th>
<th>Delta</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTTP traffic</td>
<td>605 ms</td>
<td>139 ms</td>
<td>-77%</td>
</tr>
<tr>
<td>Reactive processing</td>
<td>10.7 sec</td>
<td>3.48 sec</td>
<td>-67%</td>
</tr>
</tbody>
</table>
<h3>Learn more</h3>
<p>Visit the <a rel="nofollow" href="https://rstudio.github.io/promises/" target="_blank">promises</a> website to learn more, or watch my <a rel="nofollow" href="https://www.rstudio.com/resources/videos/scaling-shiny-apps-with-async-programming-june-2018/" target="_blank">recent webinar</a> on Shiny async.</p>
<p>See the <a rel="nofollow" href="http://shiny.rstudio.com/reference/shiny/1.1.0/upgrade.html" target="_blank">full changelog</a> for Shiny v1.1.0.</p>
<h2>Related packages</h2>
<p>Over the last year, we created or enhanced several other packages to support async Shiny:</p>
<ul>
<li>The <strong><a rel="nofollow" href="https://rstudio.github.io/promises/" target="_blank">promises</a></strong> package (released 2018-04-13) mentioned above provides the actual API you’ll use to do async programming in R. We implemented this as a separate package so that other parts of the R community, not just Shiny users, can take advantage of these techniques. The promises package was inspired by the basic ideas of <a rel="nofollow" href="https://developers.google.com/web/fundamentals/primers/promises" target="_blank">JavaScript promises</a>, but also have significantly improved syntax and extensibility to make them work well with R and Shiny. Currently, promises is most useful when used with the <a rel="nofollow" href="https://cran.r-project.org/package=future" target="_blank">future</a> package by <a rel="nofollow" href="https://github.com/HenrikBengtsson" target="_blank">Henrik Bengtsson</a>.</li>
<li><strong><a rel="nofollow" href="https://cran.r-project.org/package=later" target="_blank">later</a></strong> (released 2017-06-25) adds a low-level feature to R that is critical to async programming: the ability to schedule R code to be executed in the future, within the same R process. You can do all sorts of cool stuff on top of this, as some people are <a rel="nofollow" href="https://yihui.name/en/2017/10/later-recursion/" target="_blank">discovering</a>.</li>
<li><strong><a rel="nofollow" href="https://cran.r-project.org/package=httpuv" target="_blank">httpuv</a></strong> (1.4.0 released 2018-04-19) has long been the HTTP web server that Shiny, and most other web frameworks for R, sit on top of. Version 1.4.0 adds support for asynchronous handling of HTTP requests, and also adds a dedicated I/O-handling thread for greatly improved performance under load.</li>
</ul>
<p>In the coming weeks, you can also expect updates for async compatibility to <strong><a rel="nofollow" href="https://www.htmlwidgets.org/" target="_blank">htmlwidgets</a></strong>, <strong><a rel="nofollow" href="https://plot.ly/r/" target="_blank">plotly</a></strong>, and <strong><a rel="nofollow" href="https://rstudio.github.io/DT/" target="_blank">DT</a></strong>. Most other HTML widgets will automatically become async compatible once htmlwidgets is updated.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://blog.rstudio.com/2018/06/26/shiny-1-1-0/"> RStudio Blog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/JJnnUVTMWTE" height="1"></a></div>