<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/rcase4base-code-profiling-with-base-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://jozefhajnala.gitlab.io/r/r004-profiling/"> Jozef's Rblog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<div>
<h1>Introduction</h1>
<p>In this summertime post in the <a rel="nofollow" href="http://jozefhajnala.gitlab.io/r/categories/rcase4base/" target="_blank">case4base series</a>, we will look at useful tools in base R, which let us profile our code without any extra packages needed to be installed. We will cover simple and easy to use speed profiling, more complex profiling of performance and memory and, as always, look at alternatives to base R as well, with a special shout out to profiling integration in RStudio.</p>
</div>
<div>
<h1>Contents</h1>
<ol>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#simple-time-profiling-with-system.time" target="_blank">Simple time profiling with system.time</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#profile-r-execution-with-rprof" target="_blank">Profile R execution with Rprof</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#non-sampling-memory-use-profiling-with-rprofmem" target="_blank">Non-sampling memory use profiling with Rprofmem</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#profiling-integration-within-rstudio" target="_blank">Profiling integration within RStudio</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#background-profiling-with-base-r-via-an-rstudio-addin" target="_blank">Background profiling with base R via an RStudio addin</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#alternatives-to-base-r" target="_blank">Alternatives to base R</a></li>
<li><a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#references" target="_blank">References</a></li>
</ol>
</div>
<div>
<h1>Simple time profiling with <code>system.time</code></h1>
<p>Base function <code>system.time</code> returns the difference between two <code>proc.time</code> calls within which it evaluates an expression provided as argument. The simplest usage can be seen below:</p>
<pre><code>system.time(runif(10^8))</code></pre>
<pre><code>##    user  system elapsed 
##   4.660   0.392   5.186</code></pre>
<p>For the purpose of processing the results, we can of course store and examine them within a variable where we can see that it is in fact a numeric vector with 5 elements with a <code>proc_time</code> class. It uses <code>summary</code> as its print method via the <code>print.proc_time</code>. For most our purposes, we would be interested in the â€œelapsedâ€� element of the result, giving us the â€˜realâ€<img alt="™" src="https://s.w.org/images/core/emoji/11/72x72/2122.png" class="wp-smiley"> elapsed time since the process was started:</p>
<pre><code>tm &lt;- system.time(runif(10^8))
str(tm)</code></pre>
<pre><code>## Class 'proc_time'  Named num [1:5] 4.49 0.38 4.97 0 0
##   ..- attr(*, &quot;names&quot;)= chr [1:5] &quot;user.self&quot; &quot;sys.self&quot; &quot;elapsed&quot; &quot;user.child&quot; ...</code></pre>
<pre><code>tm[&quot;elapsed&quot;]</code></pre>
<pre><code>## elapsed 
##   4.969</code></pre>
<p>We can also very simply run multiple observations for an expression and investigate the results:</p>
<pre><code>expr &lt;- rep(expression(runif(10^8)), 10L)
tm &lt;- unlist(lapply(expr, function(x) system.time(eval(x))[&quot;elapsed&quot;]))
summary(tm)</code></pre>
<pre><code>##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.873   4.946   4.980   5.055   5.059   5.432</code></pre>
<p>With a little tweaking we can also run it in a separate process to not block our R session:</p>
<pre><code>script &lt;- paste(
  'expr &lt;- rep(expression(runif(10^7)), 10L)',
  'tm &lt;- unlist(lapply(expr, function(x) system.time(eval(x))[&quot;elapsed&quot;]))',
  'print(summary(tm))',
  sep = ';')
system2(command = 'Rscript',
        args = c('-e', shQuote(script)),
        wait = FALSE)</code></pre>
</div>
<div>
<h1>Profile R execution with <code>Rprof</code></h1>
<p>The utils package included in the base R releases contains a very useful pair of functions for profiling by sampling every interval of seconds:</p>
<ul>
<li>Use <code>utils::Rprof()</code> to enable the R profiling, run the code to be profiled and use <code>utils::Rprof(NULL)</code> to disable profiling</li>
<li>Afterwards, use <code>utils::summaryRprof()</code> to investigate the results</li>
</ul>
<p>The most simplistic usage is really this straight-forward:</p>
<pre><code># Enable profiling
utils::Rprof()

# Run the code to be profiled
x &lt;- lapply(10^(6:7),  runif)
y &lt;- lapply(x, summary)
z &lt;- sort(x[[2]])

# Disable profiling
utils::Rprof(NULL)

# Read the profiling results and view
res &lt;- utils::summaryRprof()
res[[&quot;by.self&quot;]]</code></pre>
<p>The profiling can be customized with arguments such as <code>filename</code>, which specifies to which file will the results be written (and also serves as the off switch if set to <code>NULL</code> or <code>&quot;&quot;</code>), <code>interval</code>, which governs the time between profiling samples. More can be found in the functionâ€<img alt="™" src="https://s.w.org/images/core/emoji/11/72x72/2122.png" class="wp-smiley">s help.</p>
<p>Perhaps the most interesting argument is <code>memory.profiling</code> which if set to <code>TRUE</code> will add memory information into the results file:</p>
<pre><code># Enable profiling with memory profiling
utils::Rprof(filename = &quot;ProfwMemory.out&quot;, memory.profiling = TRUE)

# Run the code to be profiled
x &lt;- lapply(10^(6:7),  runif)
y &lt;- lapply(x, summary)
z &lt;- sort(x[[2]])

# Disable profiling
utils::Rprof(NULL)

# Read the profiling results and view results in different ways
utils::summaryRprof(filename = &quot;ProfwMemory.out&quot;,
                    memory = c(&quot;stats&quot;),
                    lines = &quot;show&quot;)
utils::summaryRprof(filename = &quot;ProfwMemory.out&quot;,
                    memory = c(&quot;both&quot;))[[&quot;by.self&quot;]]</code></pre>
</div>
<div>
<h1>Non-sampling memory use profiling with <code>Rprofmem</code></h1>
<p>Base R also offers an option to profile memory use (if R is compiled with <code>R_MEMORY_PROFILING</code> defined) using <code>Rprofmem</code> – a pure memory use profiler. Results are written as simple text into a file, from which they can be read, however the processing of the result may use a bit more polishing here:</p>
<pre><code># Enable memory profiling profiling
utils::Rprofmem(&quot;Rprofmem.out&quot;, threshold = 10240)

# Run the code to be profiled
x &lt;- runif(10^5)
y &lt;- runif(10^6)
z &lt;- runif(10^7)

# Disable profiling
utils::Rprofmem(NULL)

# Read the results
readLines(&quot;Rprofmem.out&quot;)</code></pre>
<p>If our concern is specifically copying of (large) objects which negatively impact the memory requirements of our work, we can (provided that R is compiled with <code>--enable-memory-profiling</code>). Use <code>tracemem(object)</code> to mark <code>object</code> for tracking and print a stack trace it is duplicated. <code>untracemem(object)</code> untraces the object.</p>
<p>For more details see the <a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r004-profiling/#references" target="_blank">references</a> section.</p>
</div>
<div>
<h1>Profiling integration within RStudio</h1>
<p>Even though this does not really adhere to the <code>case4base</code> rules, we still mention the RStudio profiling integration, which is done using the <code>profvis</code> package and if successful, works really well and provides informative graphical outputs. All we have to to it either select a chunk of code and click on <code>Profile -> Profile Selected Line(s)</code>, or click on <code>Profile -> Start Profiling</code>, run our code and then <code>Profile -> Stop profiling</code>. RStudio should then automatically use <code>profvis</code> to produce an interactive output that allows nice exploration of the results:</p>
<div>
<img alt="RStudio+profvis" src="https://i1.wp.com/jozefhajnala.gitlab.io/r/img/r004-01-rstudio-profvis.gif?w=456&ssl=1" data-recalc-dims="1">
<p>RStudio+profvis</p>
</div>
</div>
<div>
<h1>Background profiling with base R via an RStudio addin</h1>
<p>We have also created and written about an RStudio addin that let users profile R code selected in RStudio, with the advantage that the profiling runs asynchronously in a separate process not blocking the current R session and also not requiring external packages such as profvis. You can <a rel="nofollow" href="https://jozefhajnala.gitlab.io/r/r105-async-profiler/" target="_blank">read more about it and get it here</a>.</p>
</div>
<div>
<h1>Alternatives to base R</h1>
<ul>
<li><a rel="nofollow" href="https://cran.r-project.org/web/packages/proftools/index.html" target="_blank">proftools</a> and its <a rel="nofollow" href="https://cran.r-project.org/web/packages/proftools/vignettes/proftools.pdf" target="_blank">package vignette</a></li>
<li><a rel="nofollow" href="https://github.com/rstudio/profvis" target="_blank">profvis::profvis</a></li>
<li><a rel="nofollow" href="https://cran.r-project.org/web/packages/microbenchmark/" target="_blank">microbenchmark::microbenchmark</a></li>
</ul>
</div>
<div>
<h1>References</h1>
<ol>
<li><a rel="nofollow" href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Profiling-R-code-for-speed" target="_blank">Profiling R code for speed</a> at Writing R Extensions</li>
<li><a rel="nofollow" href="https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Profiling-R-code-for-memory-use" target="_blank">Profiling R code for memory use</a> at Writing R Extensions</li>
<li><a rel="nofollow" href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/system.time.html" target="_blank">system.time help</a></li>
<li><a rel="nofollow" href="https://developer.r-project.org/memory-profiling.html" target="_blank">Memory profiling</a> in R</li>
</ol>
<h2>Did you find the article helpful or interesting? Help others find it by sharing</h2>
<div></div>
</div>
	<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://jozefhajnala.gitlab.io/r/r004-profiling/"> Jozef's Rblog</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/4k8Z5l1Fg_Q" height="1"></a></div>