<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://engineerdanny.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://engineerdanny.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2025-08-08T00:10:54+00:00</updated><id>https://engineerdanny.github.io/feed.xml</id><subtitle>International PhD researcher specializing in statistical modeling and machine learning for microbiome analysis. Recipient of prestigious international research funding and upcoming researcher at INRAE, France.</subtitle><entry><title type="html">Heading to France: My INRAE Research Internship Journey</title><link href="https://engineerdanny.github.io/blog/2025/France-INRAE-Internship/" rel="alternate" type="text/html" title="Heading to France: My INRAE Research Internship Journey"/><published>2025-01-07T10:00:00+00:00</published><updated>2025-01-07T10:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2025/France-INRAE-Internship</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2025/France-INRAE-Internship/"><![CDATA[<p>As we begin 2025, I’m thrilled to share some exciting news about the next chapter in my research journey. <strong>This April, I’ll be heading to Paris, France</strong> for a four-month research internship at <a href="https://www.inrae.fr/">INRAE</a> (National Research Institute for Agriculture, Food and Environment) in collaboration with <a href="https://www.universite-paris-saclay.fr/">Université Paris-Saclay</a>.</p> <h2 id="-research-focus-poisson-log-normal-models">🎯 Research Focus: Poisson Log-Normal Models</h2> <p>My research at INRAE will focus on <strong>comprehensive benchmarking of Poisson Log-Normal (PLN) models</strong>, a cutting-edge statistical framework for analyzing microbial data. This work represents a natural extension of my <a href="https://bmcbioinformatics.biomedcentral.com/articles/10.1186/s12859-025-06083-7">published research</a> on cross-validation methods for network inference algorithms.</p> <h3 id="what-are-pln-models">What are PLN Models?</h3> <p>Poisson Log-Normal models provide a sophisticated framework for analyzing <strong>count data with complex correlation structures</strong> - exactly the kind of data we encounter in microbiome research. These models excel at:</p> <ul> <li><strong>Principal Component Analysis</strong> for high-dimensional biological data</li> <li><strong>Abundance prediction</strong> in microbial communities</li> <li><strong>Network inference</strong> for understanding species interactions</li> </ul> <h3 id="the-research-challenge">The Research Challenge</h3> <p>While PLN models show great theoretical promise, there’s been limited systematic comparison of their performance against traditional approaches. My internship will address this gap by:</p> <ol> <li><strong>Benchmarking PLN models</strong> across three key applications</li> <li><strong>Running large-scale cross-validation experiments</strong> to quantify performance gains</li> <li><strong>Demonstrating practical advantages</strong> over generalized linear models for microbial count prediction</li> </ol> <h2 id="-prestigious-international-funding">💰 Prestigious International Funding</h2> <p>This opportunity has been made possible through an extraordinary combination of <strong>international research awards</strong> totaling over €25,000:</p> <h3 id="-pbeee-research-mobility-scholarship-12000-cad">🇨🇦 PBEEE Research Mobility Scholarship ($12,000 CAD)</h3> <p>The <a href="https://frq.gouv.qc.ca/en/program/pbeee-international-internships-program/">Quebec government’s prestigious scholarship</a> for short-term international research collaborations. This highly competitive award supports research exchanges between institutions in different countries.</p> <h3 id="-international-mobility-grant-13500">🇪🇺 International Mobility Grant (€13,500)</h3> <p>Awarded by the <a href="https://dataia.eu/">DATAIA Institute</a>, this grant is specifically designed to support research collaboration and student exchange between institutions in different countries.</p> <h3 id="-inrae-junior-scientific-mobility-program-2300">🇫🇷 INRAE Junior Scientific Mobility Program (€2,300)</h3> <p>The <a href="https://www.inrae.fr/">INRAE Hadamard initiative</a> designed to foster scientific exchange and collaboration among researchers.</p> <h2 id="-building-international-research-networks">🌍 Building International Research Networks</h2> <p>This internship represents more than just a research project - it’s about <strong>building lasting international collaborations</strong> that will shape the future of computational biology research.</p> <h3 id="key-collaborators">Key Collaborators</h3> <p>I’ll be working with leading researchers in statistical modeling and computational biology:</p> <ul> <li><strong>Dr. Julien Chiquet</strong> - Expert in statistical learning for biological networks</li> <li><strong>Dr. Mahendra Mariadassou</strong> - Specialist in microbiome data analysis</li> <li><strong>Dr. Stéphane Robin</strong> - Pioneer in statistical models for biological data</li> </ul> <p>Their collective expertise in PLN models, combined with my background in cross-validation and high-performance computing, creates an ideal environment for groundbreaking research.</p> <h3 id="bridging-continents">Bridging Continents</h3> <p>This collaboration creates a <strong>unique tri-continental research network</strong>:</p> <ul> <li>🇺🇸 <strong>North America</strong>: High-performance computing expertise (NAU’s Monsoon cluster)</li> <li>🇫🇷 <strong>Europe</strong>: Advanced statistical modeling frameworks (INRAE’s PLN expertise)</li> <li>🇨🇦 <strong>Quebec Network</strong>: Methodological validation through government-supported collaboration</li> </ul> <h2 id="-expected-impact">🔬 Expected Impact</h2> <p>The outcomes of this internship will have broad implications for:</p> <h3 id="academic-research">Academic Research</h3> <ul> <li><strong>Methodological advances</strong> in statistical modeling for biological data</li> <li><strong>Open-source software</strong> contributions to the R/Python ecosystem</li> <li><strong>Joint publications</strong> bridging American and European research communities</li> </ul> <h3 id="practical-applications">Practical Applications</h3> <ul> <li><strong>Improved microbiome analysis</strong> for medical diagnosis</li> <li><strong>Better understanding</strong> of microbial community dynamics</li> <li><strong>Enhanced predictive models</strong> for ecological and health applications</li> </ul> <h2 id="-looking-forward">📈 Looking Forward</h2> <p>The four months in Paris will be intense and productive, but I’m most excited about the <strong>long-term collaborations</strong> this will establish. International research partnerships are crucial for tackling the complex challenges in computational biology and statistical modeling.</p> <h3 id="whats-next">What’s Next?</h3> <p>Over the coming months, I’ll be:</p> <ol> <li><strong>Finalizing research protocols</strong> and computational approaches</li> <li><strong>Preparing for the cultural transition</strong> - brushing up on my French! 🇫🇷</li> <li><strong>Setting up remote access</strong> to NAU’s computing resources for seamless collaboration</li> <li><strong>Planning knowledge transfer</strong> activities to share insights with both institutions</li> </ol> <h2 id="-reflections-on-international-research">💭 Reflections on International Research</h2> <p>This opportunity reinforces my belief that the <strong>most impactful research happens at the intersection</strong> of different expertise, cultures, and approaches. The combination of American innovation in high-performance computing with European sophistication in statistical theory promises to yield insights neither approach could achieve alone.</p> <p>As I prepare for this journey, I’m grateful for the <strong>support from multiple funding agencies</strong> that recognize the value of international collaboration in advancing scientific knowledge.</p> <hr/> <p><strong>Stay tuned</strong> for updates from Paris! I’ll be sharing insights about the research process, cultural experiences, and hopefully some exciting preliminary results as they develop.</p> <p><em>Have questions about international research opportunities, funding applications, or PLN models? Feel free to <a href="mailto:da2343@nau.edu">reach out</a> - I’m always happy to discuss research and collaboration opportunities.</em></p> <h2 id="-related-resources">🔗 Related Resources</h2> <ul> <li><a href="https://bmcbioinformatics.biomedcentral.com/articles/10.1186/s12859-025-06083-7">My BMC Bioinformatics Publication</a></li> <li><a href="https://www.inrae.fr/">INRAE Research Institute</a></li> <li><a href="https://frq.gouv.qc.ca/en/program/pbeee-international-internships-program/">PBEEE Scholarship Program</a></li> <li><a href="https://dataia.eu/">DATAIA Institute</a></li> </ul>]]></content><author><name></name></author><category term="research"/><category term="international"/><category term="research"/><category term="collaboration"/><category term="france"/><category term="inrae"/><category term="statistical-modeling"/><summary type="html"><![CDATA[Announcing my upcoming research internship at INRAE/Université Paris-Saclay, funded by prestigious international awards totaling over €25,000.]]></summary></entry><entry><title type="html">ML with Monsoon</title><link href="https://engineerdanny.github.io/blog/2023/ML-With-Monsoon/" rel="alternate" type="text/html" title="ML with Monsoon"/><published>2023-09-02T00:00:00+00:00</published><updated>2023-09-02T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2023/ML-With-Monsoon</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2023/ML-With-Monsoon/"><![CDATA[<h2 id="introduction">Introduction</h2> <p>Welcome to the ML with Monsoon project! This blog post will guide you through some of the essential steps in setting up and executing machine learning workflows using the Monsoon HPC cluster. Monsoon is a high-performance computing (HPC) cluster at Northern Arizona University. It is a shared resource that provides researchers with the computational power needed to run large-scale simulations and data analysis. Although Monsoon is a powerful tool, it can be challenging to use for beginners. This blog post aims to provide a step-by-step guide to help you get started with machine learning on Monsoon. The concepts covered in this project will be applicable to any HPC cluster, so even if you are not using Monsoon, you can still benefit from this guide. We will cover how to connect to Monsoon, perform interactive debugging, submit batch jobs, and visualize key results.</p> <h2 id="connecting-to-monsoon">Connecting to Monsoon</h2> <p>To start using Monsoon, you can connect via the dashboard or through a secure shell (ssh).</p> <ul> <li> <p>Access through the monsoon <a href="https://ondemand.hpc.nau.edu/pun/sys/dashboard/">dashboard</a> Navigate to the Monsoon Dashboard and log in with your credentials.</p> </li> <li> <p>Access through the secure shell (ssh). Open your terminal and run the following command, replacing <username> with your actual NAU username. You will be prompted to enter your password.</username></p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-Y</span> &lt;username&gt;@monsoon.hpc.nau.edu
</code></pre></div> </div> </li> </ul> <h2 id="interactivedebug-work">Interactive/Debug Work</h2> <p>For interactive or debugging tasks, you can request a compute node. Here are two examples:</p> <ul> <li>Request a node with 4GB of RAM and 1 CPU for 24 hours: <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>srun <span class="nt">-t</span> 24:00:00 <span class="nt">--mem</span><span class="o">=</span>4GB <span class="nt">--cpus-per-task</span><span class="o">=</span>1 <span class="nt">--pty</span> bash
</code></pre></div> </div> </li> <li>Request a node with 8GB of RAM and 1 CPU for 1 hour to run a Python script. <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>srun <span class="nt">-t</span> 1:00:00 <span class="nt">--mem</span><span class="o">=</span>8GB <span class="nt">--cpus-per-task</span><span class="o">=</span>1 python analysis.py
</code></pre></div> </div> </li> </ul> <h2 id="submitting-jobs">Submitting Jobs</h2> <p>For longer-running tasks, you can write a job script and submit it to the queue. Here is an example of a job script (jobscript.sh):</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c">#SBATCH --job-name=test</span>
<span class="c">#SBATCH --output=/scratch/da2343/output.txt </span>
<span class="c">#SBATCH --error=/scratch/da2343/error.txt </span>
<span class="c">#SBATCH --time=20:00</span>
<span class="c">#SBATCH --mem=1GB</span>
<span class="c">#SBATCH --cpus-per-task=1</span>
python analysis.py
</code></pre></div></div> <p>Submit the job script using the following command:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sbatch jobscript.sh
</code></pre></div></div> <h2 id="visualizing-results">Visualizing Results</h2> <h3 id="time-graph"><a href="https://github.com/EngineerDanny/ml_with_monsoon/tree/main/code/job_arrays_intermediate">Time Graph</a></h3> <p>Understanding the time performance of your machine learning models is crucial. The following graph illustrates the time taken for different stages in the workflow.</p> <div class="row"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/time_graph-480.webp 480w,/assets/img/time_graph-800.webp 800w,/assets/img/time_graph-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/time_graph.png" class="img-fluid rounded z-depth-1" width="700px" height="500px" title="time_graph" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> </div> </div> <h3 id="algorithm-selection"><a href="https://github.com/EngineerDanny/ml_with_monsoon/tree/main/code/job_arrays_advanced">Algorithm Selection</a></h3> <p>Choosing the right algorithm can significantly impact the performance and accuracy of your model. Below is a graph showing the accuracy of different parallel algorithms.</p> <div class="row"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/parallel_algo_acc-480.webp 480w,/assets/img/parallel_algo_acc-800.webp 800w,/assets/img/parallel_algo_acc-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/parallel_algo_acc.png" class="img-fluid rounded z-depth-1" width="700px" height="500px" title="parallel_algo_acc" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> </div> </div> <h3 id="hyper-parameter-tuning"><a href="https://github.com/EngineerDanny/ml_with_monsoon/tree/main/code/optimization">Hyper-Parameter Tuning</a></h3> <p>Hyper-parameter tuning is essential for optimizing the performance of your machine learning models. The following graph shows the loss during hyper-parameter tuning.</p> <div class="row"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/loss_df_01-480.webp 480w,/assets/img/loss_df_01-800.webp 800w,/assets/img/loss_df_01-1400.webp 1400w," sizes="95vw" type="image/webp"/> <img src="/assets/img/loss_df_01.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" title="loss_df_01" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> </div> </div> <h2 id="conclusion">Conclusion</h2> <p>In this post, we’ve walked you through the essential steps for setting up and managing machine learning workflows on the Monsoon HPC cluster. From connecting to Monsoon and performing interactive debugging, to submitting jobs and visualizing results, these guidelines are designed to help you efficiently utilize Monsoon’s powerful resources.</p> <p>Harnessing the capabilities of high-performance computing can significantly accelerate your machine learning projects, enabling you to handle larger datasets, run more complex models, and achieve faster results. By following the steps outlined here, you can optimize your workflow, reduce development time, and focus on what matters most—building and refining your machine learning models.</p>]]></content><author><name></name></author><category term="python"/><category term="git"/><category term="github"/><category term="ml"/><category term="monsoon"/><summary type="html"><![CDATA[This post explains some of the basic concepts you will need in your machine learning workflow using monsoon.]]></summary></entry><entry><title type="html">Setting Up Github CI With Rperform</title><link href="https://engineerdanny.github.io/blog/2022/Setting-Up-Github-CI-With-Rperform/" rel="alternate" type="text/html" title="Setting Up Github CI With Rperform"/><published>2022-09-01T00:00:00+00:00</published><updated>2022-09-01T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Setting-Up-Github-CI-With-Rperform</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Setting-Up-Github-CI-With-Rperform/"><![CDATA[<h3 id="introduction">Introduction</h3> <p>Rperform has great flexibility and usability. It internally supports automating the tests of your code on Github and creating comments to display the results. To set-up Rperform for your GitHub CI worflow, initialize Rperform with the command :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Rperform</span><span class="o">:</span><span class="n">init_rperform</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <ul> <li> <p>The above command creates the Github workflow directory, which is the <code class="language-plaintext highlighter-rouge">.github/workflow/</code> directory and populates it with the needed workflow files (<code class="language-plaintext highlighter-rouge">rperform-receive.yaml</code> and <code class="language-plaintext highlighter-rouge">rperform-comment.yaml</code>).</p> </li> <li> <p>It also creates the <code class="language-plaintext highlighter-rouge">rperform</code> directory and populates it with files which make test configuration and customisation easier.</p> </li> </ul> <h3 id="running-the-script">Running the script</h3> <p>One of the most important files in the <code class="language-plaintext highlighter-rouge">rperform</code> directory is the <code class="language-plaintext highlighter-rouge">script.R</code> file, which is where the Rperform test functions should be written. The functions written in the file will be ran when the workflow is triggered. You can write multiple Rperform functions in the <code class="language-plaintext highlighter-rouge">script.R</code> file.</p> <p>With only these two functions, you can run four different types of tests:</p> <ol> <li><code class="language-plaintext highlighter-rouge">Rperform::plot_metrics()</code></li> <li><code class="language-plaintext highlighter-rouge">Rperform::plot_branchmetrics()</code></li> </ol> <p><strong>NOTE:</strong> The <code class="language-plaintext highlighter-rouge">save_plot</code> and <code class="language-plaintext highlighter-rouge">save_image</code> parameters must always be set to <code class="language-plaintext highlighter-rouge">TRUE</code> so that the outputs will be saved and displayed without any issues.</p> <p>After this set-up, anytime there is a Pull Request in the repository, the workflow will be triggered and the tests will be run. The results will be commented out by Github Bot in the PR.</p> <h3 id="customising-the-pr-comment">Customising the PR comment</h3> <p>There are the <code class="language-plaintext highlighter-rouge">header.R</code> and <code class="language-plaintext highlighter-rouge">footer.R</code> files inside the <code class="language-plaintext highlighter-rouge">rperform</code> directory which you can edit to customize the PR comment. The <code class="language-plaintext highlighter-rouge">glue</code> package is used to format and interpolate the strings so as to join the different sections of the comment. It must be noted that since any comment text is rendered in Markdown format, you must use the markdown syntax to edit the comment.</p> <h3 id="results">Results</h3> <p>Below is an example of the auto comment that is generated when the workflow is triggered by a PR.</p> <p><img width="824" alt="Screenshot 2022-08-12 at 11 55 57 AM" src="https://user-images.githubusercontent.com/47421661/184349192-2231a797-2de9-4de5-bf34-07ce49ac90db.png"/></p> <h3 id="testing-rperform-on-popular-r-packages">Testing Rperform on Popular R packages</h3> <p><strong>Rperform Test 1</strong></p> <ul> <li> <p>Test on the <a href="https://github.com/r-lib/styler">styler</a> package, main repository <a href="https://github.com/EngineerDanny/styler">here</a>.</p> </li> <li> <p>Inside the <code class="language-plaintext highlighter-rouge">script.R</code> file, the following changes were made. Basically, the tests paths were updated to run the time_metrics functions. Below is the image of the updated script.R file.</p> </li> </ul> <div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">## TEST 1</span><span class="w">
</span><span class="n">Rperform</span><span class="o">::</span><span class="n">plot_metrics</span><span class="p">(</span><span class="w">
  </span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-rmd.R"</span><span class="p">,</span><span class="w">
  </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">140</span><span class="p">,</span><span class="w">
  </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
  </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
  </span><span class="n">total_width_in</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">20</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="c1">## TEST 2</span><span class="w">
</span><span class="n">Rperform</span><span class="o">::</span><span class="n">plot_metrics</span><span class="p">(</span><span class="w">
  </span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-escaping.R"</span><span class="p">,</span><span class="w">
  </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">140</span><span class="p">,</span><span class="w">
  </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
  </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
  </span><span class="n">total_width_in</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">20</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <ul> <li>Sample <a href="https://github.com/EngineerDanny/styler/pull/1#issuecomment-1229242369">comment</a> created by running the tests. <img width="684" alt="Screenshot 2022-09-04 at 4 46 58 PM" src="https://user-images.githubusercontent.com/47421661/188338179-cc4f8371-29ff-4745-91e4-0a6282806b75.png"/></li> </ul> <p><strong>Rperform Test 2</strong></p> <ul> <li> <p>Test on the <a href="https://github.com/r-lib/devtools">devtools</a> package, original repository <a href="https://github.com/r-lib/devtools">here</a>.</p> </li> <li> <p>The <code class="language-plaintext highlighter-rouge">script.R</code> file is shown below :</p> </li> </ul> <div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">## TEST 1</span><span class="w">
</span><span class="n">Rperform</span><span class="o">::</span><span class="n">plot_metrics</span><span class="p">(</span><span class="w">
    </span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-utils.R"</span><span class="p">,</span><span class="w">
    </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">100</span><span class="p">,</span><span class="w">
    </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
    </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
    </span><span class="n">total_width_in</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">30</span><span class="w">
</span><span class="p">)</span><span class="w">

</span><span class="c1">## TEST 2</span><span class="w">
</span><span class="n">Rperform</span><span class="o">::</span><span class="n">plot_metrics</span><span class="p">(</span><span class="w">
    </span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-check.R"</span><span class="p">,</span><span class="w">
    </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"memory"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">100</span><span class="p">,</span><span class="w">
    </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
    </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">TRUE</span><span class="p">,</span><span class="w">
    </span><span class="n">total_width_in</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">30</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <ul> <li>Sample <a href="https://github.com/EngineerDanny/devtools/pull/1#issuecomment-1229734119">comment</a> created by running the tests.</li> </ul> <p><img width="914" alt="Screenshot 2022-09-04 at 7 23 14 PM" src="https://user-images.githubusercontent.com/47421661/188348860-1a94a080-eaf0-455d-a6d1-299617269df2.png"/></p>]]></content><author><name></name></author><category term="rperform"/><category term="test"/><category term="r"/><summary type="html"><![CDATA[How to set-up Rperform Github CI]]></summary></entry><entry><title type="html">Implementing Custom Github Action Prototype in Rperform</title><link href="https://engineerdanny.github.io/blog/2022/Implementing-Custom-Github-Actions-in-Rperform/" rel="alternate" type="text/html" title="Implementing Custom Github Action Prototype in Rperform"/><published>2022-07-05T00:00:00+00:00</published><updated>2022-07-05T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Implementing-Custom-Github-Actions-in-Rperform</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Implementing-Custom-Github-Actions-in-Rperform/"><![CDATA[<h2 id="abstract">ABSTRACT</h2> <p>In my previous <a href="">article</a>, I established the reason why Github Actions was the preferred choice over other tools like <a href="https://www.travis-ci.com">Travis CI</a> and <a href="https://www.appveyor.com/">Appveyor</a>. The main goal of this project as described <a href="https://github.com/rstats-gsoc/gsoc2022/wiki/RPerform">here</a> is to get Rperform working and easy to use with <code class="language-plaintext highlighter-rouge">Github Actions</code>. GitHub Actions enable DevOps to be done on Github and allows workflows to be run when other events are triggered in the repository. GitHub provides macOS, Linux and Windows virtual machines to run workflows. A workflow is a configurable process defined by YAML file which contains one or more jobs that may be run sequencially or parallel. Each job runs inside it’s own container or runner. Under each job, there are steps that runs a script or an action.</p> <h2 id="development-considerations">DEVELOPMENT CONSIDERATIONS</h2> <h3 id="the-repository">The repository</h3> <p>To develop a custom Github Actions, I had to consider whether to keep it in the main repository or create a new repository just for the Github Actions. I decided to keep it in the main repository because it is easier to maintain along with the main package as well. The main reason why I chose to do that was because this particular Github Action is specific to only this package and it is not generalized enough to be used with other packages.</p> <p>The only issue that I thought of was version control of the action. However, it can be fixed by specifying the version number of the action which must be the same as the version number of the Rperform package. e.g. <code class="language-plaintext highlighter-rouge">Rperform v0.0.1</code>:</p> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="s">uses EngineerDanny/Rperform/actions/receive@v0.0.1</span>
</code></pre></div></div> <h3 id="the-type-of-action">The Type of Action</h3> <p>According to the <a href="https://docs.github.com/en/actions/creating-actions/about-custom-actions#types-of-actions">documentation</a>, there are only three types of actions namely :</p> <ul> <li>Docker Container which supports only Linux OS</li> <li>Javascript which supports Linux, MacOS and Windows</li> <li><strong>Composite Actions</strong> which also support Linux, MacOS and Windows.</li> </ul> <p>Even though all the other types of actions are very important, I chose to use composite actions. It allows the combination of multiple workflow steps within one action. This feature makes it possible to combine multiple run commands into an action. If a workflow is set-up, it can execute the commands as a single step with that action. This flexibility is the main reason why I adopted this approach.</p> <h2 id="implementing-custom-github-actions-prototype">IMPLEMENTING CUSTOM GITHUB ACTIONS PROTOTYPE</h2> <p>I submitted a <a href="https://github.com/EngineerDanny/Rperform/pull/7">PR</a> which intends to create Github Actions to make it easier for package developers to use Rperform to test their code. The Actions are tested on a separate repository <a href="https://github.com/EngineerDanny/stringr/pull/2">stringr</a>.</p> <p>To make set-up easier, the Github workflow directory, which is the <code class="language-plaintext highlighter-rouge">.github/workflow/</code> directory, is created automatically when you ran <code class="language-plaintext highlighter-rouge">Rperform::init_rperform()</code> function. It is also populated with the needed workflow files to be able to run <code class="language-plaintext highlighter-rouge">Rperform</code> with ease. It adds the <code class="language-plaintext highlighter-rouge">rperform</code> directory and populates it with files which make test configuration and customisation easier. One of the most important files in that directory is the <code class="language-plaintext highlighter-rouge">script.R</code> file which is where the Rperform test functions should be written. <img width="485" alt="Screenshot 2022-07-01 at 3 33 40 PM" src="https://user-images.githubusercontent.com/47421661/176925448-eb5237f5-33ad-40e6-94a9-4c8dbaa81744.png"/></p> <p>When writing the Github Action for Rperform, I divided the action into two parts. These are the <strong><code class="language-plaintext highlighter-rouge">receive</code></strong> and <strong><code class="language-plaintext highlighter-rouge">comment</code></strong> parts. This decision was taken due to security reasons.</p> <h3 id="the-receive-action"><a href="https://github.com/EngineerDanny/Rperform/tree/main/actions/receive">The Receive Action</a></h3> <ul> <li>This action is represented by <a href="https://github.com/EngineerDanny/Rperform/tree/main/actions/receive">EngineerDanny/Rperform/actions/receive</a> <ul> <li>Triggered via PR or push to main branch.</li> <li>Reads <code class="language-plaintext highlighter-rouge">config.json</code> to prepare and run the benchmark job.</li> <li>Does not have read or write access due to <a href="https://securitylab.github.com/research/github-actions-preventing-pwn-requests/">security reasons</a>.</li> </ul> </li> <li>Below is the script inside receive.yaml file</li> </ul> <div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">receive"</span>
<span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Action</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">run</span><span class="nv"> </span><span class="s">Rperform</span><span class="nv"> </span><span class="s">benchmarks</span><span class="nv"> </span><span class="s">and</span><span class="nv"> </span><span class="s">upload</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">results."</span>
<span class="na">inputs</span><span class="pi">:</span>
  <span class="na">cache-version</span><span class="pi">:</span>
    <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Integer</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">as</span><span class="nv"> </span><span class="s">cache</span><span class="nv"> </span><span class="s">version.</span><span class="nv"> </span><span class="s">Increment</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">new</span><span class="nv"> </span><span class="s">cache."</span>
    <span class="na">required</span><span class="pi">:</span> <span class="kc">true</span>
    <span class="na">default</span><span class="pi">:</span> <span class="m">1</span>
  <span class="na">rperform_ref</span><span class="pi">:</span>
    <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Which</span><span class="nv"> </span><span class="s">branch</span><span class="nv"> </span><span class="s">or</span><span class="nv"> </span><span class="s">tag</span><span class="nv"> </span><span class="s">of</span><span class="nv"> </span><span class="s">Rperform</span><span class="nv"> </span><span class="s">should</span><span class="nv"> </span><span class="s">be</span><span class="nv"> </span><span class="s">used.</span><span class="nv"> </span><span class="s">Mainly</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">debugging."</span>
    <span class="na">required</span><span class="pi">:</span> <span class="kc">true</span>
    <span class="na">default</span><span class="pi">:</span> <span class="s2">"</span><span class="s">@github-actions"</span>

<span class="na">runs</span><span class="pi">:</span>
  <span class="na">using</span><span class="pi">:</span> <span class="s2">"</span><span class="s">composite"</span>
  <span class="na">steps</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Checkout repo</span>
      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v3</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">fetch-depth</span><span class="pi">:</span> <span class="m">0</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Set up git user</span>
      <span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
        <span class="s">git config --local user.name "GitHub Actions"</span>
        <span class="s">git config --local user.email "actions@github.com"</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Setup R</span>
      <span class="na">uses</span><span class="pi">:</span> <span class="s">r-lib/actions/setup-r@v2</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Install dependencies</span>
      <span class="na">uses</span><span class="pi">:</span> <span class="s">r-lib/actions/setup-r-dependencies@v2</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">cache-version</span><span class="pi">:</span> <span class="s">$</span>
        <span class="na">extra-packages</span><span class="pi">:</span> <span class="pi">|</span>
          <span class="s">any::ggplot2</span>
          <span class="s">any::dplyr</span>
          <span class="s">any::gert</span>
          <span class="s">any::glue</span>
          <span class="s">github::EngineerDanny/Rperform$</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Remove global installation</span>
      <span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
        <span class="s">pkg &lt;- unlist(read.dcf('DESCRIPTION')[, 'Package'])</span>
        <span class="s">if (pkg %in% rownames(installed.packages())) {</span>
          <span class="s">remove.packages(pkg)</span>
          <span class="s">cat('removed package ', pkg, '.', sep = "")</span>
        <span class="s">}</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">Rscript {0}</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Run benchmarks</span>
      <span class="na">run</span><span class="pi">:</span> <span class="s">Rperform::run_script("rperform/script.R")</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">Rscript {0}</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Uploading Results</span>
      <span class="na">run</span><span class="pi">:</span> <span class="pi">|</span>
        <span class="s">echo "Uploading results..."</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>

    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Saves the PR number in an artifact</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
      <span class="na">env</span><span class="pi">:</span>
        <span class="na">PULL_REQUEST_NUMBER</span><span class="pi">:</span> <span class="s">$</span>
      <span class="na">run</span><span class="pi">:</span> <span class="s">echo $PULL_REQUEST_NUMBER &gt; ./rperform/pr-comment/PR_NO</span>

    <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/upload-artifact@v2</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">name</span><span class="pi">:</span> <span class="s">pr</span>
        <span class="na">path</span><span class="pi">:</span> <span class="s">rperform/pr-comment/</span>
</code></pre></div></div> <h3 id="the-comment-action"><a href="https://github.com/EngineerDanny/Rperform/tree/main/actions/comment">The Comment Action</a></h3> <ul> <li>This action is represented by <a href="https://github.com/EngineerDanny/Rperform/tree/main/actions/comment">EngineerDanny/Rperform/actions/comment</a> <ul> <li>Comments the results on the PR that originated the workflow run.</li> <li>Starts right after the <code class="language-plaintext highlighter-rouge">receive</code> job finishes.</li> <li>Will create an additional commit status to the PR check suite.</li> <li>Has read &amp; write access.</li> </ul> </li> <li>Below is the script inside comment.yaml file</li> </ul> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">comment"</span>
<span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Action</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">comment</span><span class="nv"> </span><span class="s">Rperform</span><span class="nv"> </span><span class="s">results</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">appropriate</span><span class="nv"> </span><span class="s">PR.</span><span class="nv"> </span><span class="s">Needs</span><span class="nv"> </span><span class="s">read/write</span><span class="nv"> </span><span class="s">access."</span>
<span class="na">inputs</span><span class="pi">:</span>
  <span class="na">GITHUB_TOKEN</span><span class="pi">:</span>
    <span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">The</span><span class="nv"> </span><span class="s">GITHUB_TOKEN</span><span class="nv"> </span><span class="s">secret."</span>
    <span class="na">required</span><span class="pi">:</span> <span class="kc">true</span>

<span class="na">runs</span><span class="pi">:</span>
  <span class="na">using</span><span class="pi">:</span> <span class="s2">"</span><span class="s">composite"</span>
  <span class="na">steps</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Download</span><span class="nv"> </span><span class="s">artifact"</span>
      <span class="na">id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">download"</span>
      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/github-script@v3.1.0</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">script</span><span class="pi">:</span> <span class="pi">|</span>
          <span class="s">var artifacts = await github.actions.listWorkflowRunArtifacts({</span>
             <span class="s">owner: context.repo.owner,</span>
             <span class="s">repo: context.repo.repo,</span>
             <span class="s">run_id: $,</span>
          <span class="s">});</span>
          <span class="s">var matchArtifact = artifacts.data.artifacts.filter((artifact) =&gt; {</span>
            <span class="s">return artifact.name == "pr"</span>
          <span class="s">})[0];</span>
          <span class="s">var download = await github.actions.downloadArtifact({</span>
             <span class="s">owner: context.repo.owner,</span>
             <span class="s">repo: context.repo.repo,</span>
             <span class="s">artifact_id: matchArtifact.id,</span>
             <span class="s">archive_format: 'zip',</span>
          <span class="s">});</span>
          <span class="s">var fs = require('fs');</span>
          <span class="s">fs.writeFileSync('$/pr.zip', Buffer.from(download.data));</span>
    <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">unzip pr.zip</span>
      <span class="na">shell</span><span class="pi">:</span> <span class="s">bash</span>
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Comment</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">PR"</span>
      <span class="na">id</span><span class="pi">:</span> <span class="s2">"</span><span class="s">comment"</span>
      <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/github-script@v6</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">script</span><span class="pi">:</span> <span class="pi">|</span>
          <span class="s">var fs = require('fs');</span>
          <span class="s">var pr_number = Number(fs.readFileSync('./PR_NO'));</span>
          <span class="s">var body = fs.readFileSync('./results.txt').toString();</span>
          <span class="s">await github.rest.issues.createComment({</span>
            <span class="s">owner: context.repo.owner,</span>
            <span class="s">repo: context.repo.repo,</span>
            <span class="s">issue_number: pr_number,</span>
            <span class="s">body: body</span>
          <span class="s">});</span>
          
    <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/github-script@v5</span>
      <span class="na">if</span><span class="pi">:</span> <span class="s">always()</span>
      <span class="na">with</span><span class="pi">:</span>
        <span class="na">script</span><span class="pi">:</span> <span class="pi">|</span>
          <span class="s">let url = '$'</span>
          <span class="s">let any_failed = $</span>
          <span class="s">let state = 'success'</span>
          <span class="s">let description = 'Commenting succeeded!'</span>

          <span class="s">if($ || any_failed) {</span>
            <span class="s">state = 'failure'</span>
            <span class="s">description = 'Commenting failed!'</span>
            <span class="s">if(any_failed) {</span>
              <span class="s">url = "https://github.com/$/actions/runs/" + </span>
                    <span class="s">"$"</span>
            <span class="s">}</span>
          <span class="s">}</span>
          <span class="s">github.rest.repos.createCommitStatus({</span>
            <span class="s">owner: context.repo.owner,</span>
            <span class="s">repo: context.repo.repo,</span>
            <span class="s">sha: '$',</span>
            <span class="s">state: state,</span>
            <span class="s">target_url: url,</span>
            <span class="s">description: description,</span>
            <span class="s">context: 'rperform comment'</span>
          <span class="s">})</span>
</code></pre></div></div> <h2 id="conclusion">CONCLUSION</h2> <p>This is the prototype of the Github Actions. Initially due to separation of actions, I had an issue with the Github create comment script which was similar to <a href="https://github.com/actions/github-script/issues/77">this issue</a>. After several debugging and testing, I was able to successfully automate the creation of comments. <a href="https://github.com/EngineerDanny/stringr/pull/2#issuecomment-1172716652">(Auto Comment On PR)</a>. The actions are implemented in such a way that testing results are firstly uploaded as an artifact on Github. Then afterwards, a comment is created by Github actions bot on the PR. At this point, I only tested it with the <code class="language-plaintext highlighter-rouge">plot_metrics</code> function. More functionalities will be added to the actions in time. I am thinking about limiting the number of functions that can be run in the <code class="language-plaintext highlighter-rouge">script.R</code> file.</p>]]></content><author><name></name></author><category term="rperform"/><category term="test"/><category term="r"/><summary type="html"><![CDATA[My step-by-step approach to develop the prototype of custom Github Actions in Rperform.]]></summary></entry><entry><title type="html">R CMD Check on Rperform</title><link href="https://engineerdanny.github.io/blog/2022/RPerform-R-CMD-Check/" rel="alternate" type="text/html" title="R CMD Check on Rperform"/><published>2022-06-29T00:00:00+00:00</published><updated>2022-06-29T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/RPerform-R-CMD-Check</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/RPerform-R-CMD-Check/"><![CDATA[<h2 id="introduction">INTRODUCTION</h2> <p>When it comes to publishing an R package, it is very prerequisite and crucial for the package to pass <code class="language-plaintext highlighter-rouge">R CMD Check</code>. <code class="language-plaintext highlighter-rouge">R CMD Check</code> is basically a test performed on an R package to check code for common problems whilst suggesting ways of fixing them. This means that it is also great tool to even utilize during the whole development process of a package. <code class="language-plaintext highlighter-rouge">R CMD Checks</code> comprises of about 50 different tests which are explained <a href="https://r-pkgs.org/r-cmd-check.html#check-checks">here</a></p> <h2 id="running-r-cmd-check-locally">RUNNING <code class="language-plaintext highlighter-rouge">R CMD CHECK</code> LOCALLY</h2> <p>Running<code class="language-plaintext highlighter-rouge"> R CMD Check</code> on <code class="language-plaintext highlighter-rouge">Rperform</code> is a simple task. During development, it can be run locally by using the famous devtools package.</p> <div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">devtools</span><span class="o">::</span><span class="n">check</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <p>Also, the R Studio IDE has in-built features which makes it easy to run R CMD Checks right inside the IDE. Under Build section, there is a check button which does that. Using various methods above is synonymous to running the following command on the R console:</p> <div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">R</span><span class="w"> </span><span class="n">CMD</span><span class="w"> </span><span class="n">check</span><span class="w"> </span><span class="n">Rperform</span><span class="w">
</span></code></pre></div></div> <p>However, when developers need to share or collaborate on a project, the check comes in handy if it can be run online in a container for everyone to see the results. It is more challenging to set-up the checks to run online. Mostly, this approach is used when the need arises to run <code class="language-plaintext highlighter-rouge">R CMD check</code> every time changes are made in code. Since we use GitHub, it is recommended that we do that with <a href="https://github.com/features/actions">Github Actions</a>. There are others such as <a href="https://www.travis-ci.com">Travis CI</a> and <a href="https://www.appveyor.com/">Appveyor</a> but we will stick with Github Actions due to its simplicity and power. In addition to that, it implements modern technologies with vast functionalities and growing community.</p> <p>It must be taken note that running <code class="language-plaintext highlighter-rouge">R CMD Check</code> on any package will return only three types of notices:</p> <blockquote> <p><strong>ERRORS</strong> : These are issues which are very fatal and likely to cause the package or its dependencies to fail to install.</p> </blockquote> <blockquote> <p><strong>WARNINGS</strong> : Warnings are statements that are made to caution the developer to take note of certain vital issues. These issues are unlikely to be detrimental to the package but it is very crucial to not ignore them.</p> </blockquote> <blockquote> <p><strong>NOTES</strong> : Notes are not crucial issues. They are just mild problems which are meant for developers to take note of.</p> </blockquote> <p><em>R CMD Check passes successfully when none of the above notices are returned</em></p> <h2 id="r-cmd-check-using-github-actions"><code class="language-plaintext highlighter-rouge">R CMD CHECK</code> USING GITHUB ACTIONS</h2> <p><a href="https://github.com/features/actions"><code class="language-plaintext highlighter-rouge">GitHub Actions</code></a> is an open-source technology that makes it easy for automation of software workflows. It has exceptional Continuous Integration/ Continuous Deployment (CI/CD) tools which enables developers to build, test and deploy code right from their GitHub repositories.</p> <p>It is very exciting that the R community has a number of repositories of Github Actions which can be used to perform any variety of CI tasks for R projects with example workflows. In Rperform, we use the following actions sequencially :</p> <ol> <li><a href="https://github.com/actions/checkout">actions/checkout</a> - Checks out your repository to the <code class="language-plaintext highlighter-rouge">$GITHUB_WORKSPACE</code> so that repository’s workflow can utilize it.</li> <li><a href="https://github.com/r-lib/actions/tree/v2/setup-r">r-lib/actions/setup-r</a> - Sets up an <a href="https://r-project.org">R</a> environment for use in GitHub Actions by basically downloading and caching a version of R.</li> <li><a href="https://github.com/r-lib/actions/tree/v2/setup-r-dependencies">r-lib/actions/setup-r-dependencies</a> - Downloads and installs all the packages declared in the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file.</li> <li><a href="https://github.com/r-lib/actions/tree/v2/check-r-package">r-lib/actions/check-r-package</a> - Runs <code class="language-plaintext highlighter-rouge">R CMD check</code> on an R package.</li> </ol> <p>If every check passes without any discrepancies, it implies that the package is stable. However, if any of the check fails, detailed logs will be shown at the end of every action for you to rectify this issue. It can be very confusing at first when some of the checks fail but with a little bit of debugging and testing, you can get the package to pass. When you check my workflow history on my Rperform repository <a href="https://github.com/EngineerDanny/Rperform/actions">here</a>, you would notice that I have about 50% failed workflow runs. I wrote an <a href="https://engineerdanny.github.io/GSOC22-RPerform-Blog/rperform/performance/test/r/git/github/2022/06/20/Updating-dependencies-In-Rperform.html">article</a> describing a total review of how I went about fixing the issues with Rperform’s initial dependencies. At that time, I had successive workflow failures (From<code class="language-plaintext highlighter-rouge"> R-CMD-check #17</code> to<code class="language-plaintext highlighter-rouge"> R-CMD-check #21</code> ). After fixing the various issues that popped up, I submitted a <a href="https://github.com/EngineerDanny/Rperform/pull/1">Pull Request</a> explaining the series of failures and the steps I took to fix them.</p> <p>I will be diving deep into the <a href="https://github.com/EngineerDanny/Rperform/pull/1">PR</a> to explain some of the issues encountered.</p> <p><img alt="Screenshot 2022-06-22 at 11 44 48 AM" src="https://user-images.githubusercontent.com/47421661/175021313-4fcd05ff-fc67-45d1-8935-8e1ccf99feec.png"/></p> <p>From the <a href="https://github.com/EngineerDanny/Rperform/actions/runs/2536152401">Check-RPerform #3</a>, Github showed a visual evidence that points to <code class="language-plaintext highlighter-rouge">r-lib/actions/check-r-package</code> as the specific action that failed.</p> <p>Initially, the issue was invalid link in the <code class="language-plaintext highlighter-rouge">test-repo-metrics.R </code>file. I found out that the <a href="https://github.com/hadley/stringr">hadley/stringr</a> link does not exist. Even though, when you open the link you will be redirected to the actual repository which is the <a href="https://github.com/tidyverse/stringr">tidyverse/stringr</a>.</p> <p>My test results were inconsistent (Failing more times and occassionally passing) due to this issue. Therefore, I changed the github link to <a href="https://github.com/tidyverse/stringr">tidyverse/stringr</a> After running Rperform check locally, even though the test didn’t explicitly give me an error, it failed. The only warning was :</p> <blockquote> <p>checking Rd cross-references … WARNING Missing link or links in documentation object ‘Rperform-package.Rd’: ‘[git2r:git2r-package]{git2r}’</p> <p>See section ‘Cross-references’ in the ‘Writing R Extensions’ manual.</p> </blockquote> <p>I fixed the warning by inserting the <a href="https://github.com/ropensci/git2r">git2r</a> official github link.</p> <p>Although the issue with the link was fixed and <strong>R CMD Check</strong> on my local machine passed, the GitHub CI action still failed. So I started to dig into the <a href="https://github.com/tidyverse/stringr">tidyverse/stringr</a> package tests.</p> <p>Inside the https://github.com/tidyverse/stringr/blob/main/tests/testthat/test-dup.r file, there are three tests which are ran internally.</p> <p><img width="642" alt="Screenshot 2022-06-22 at 2 30 21 PM" src="https://user-images.githubusercontent.com/47421661/175054951-9392a05a-0ef8-4443-84f4-f06fa950b562.png"/></p> <p>As shown above, all the other tests passed except the <code class="language-plaintext highlighter-rouge">uses tidyverse recycling rules</code> test. This led to my conclusion that, this may be an internal issue with the <code class="language-plaintext highlighter-rouge">tidyverse/stringr</code> package.</p> <p>The first two tests however, could be used in checking Rperform.</p> <h2 id="final-fix">FINAL FIX</h2> <p>After several debugging and testing, I finally found the final error that was causing the <strong>Rperform R CMD Check</strong> test to fail on GitHub CI. It turns out that during my adventures and explorations, I mistakenly created a file( [tests/testthat/test-plot-metrics.R]) on the <code class="language-plaintext highlighter-rouge">master</code> branch.</p> <p><img width="696" alt="Screenshot 2022-06-22 at 8 14 21 PM" src="https://user-images.githubusercontent.com/47421661/175130169-1d1dd3f7-2f9e-43ec-b7cc-b88de65599ec.png"/></p> <p>As recorded from the logs above, in the file, there is an issue with the <code class="language-plaintext highlighter-rouge">str_c</code> function because it does not exist. Therefore, I removed this file since it’s not needed. It was created for experimental purposes.</p> <p>After fixing all the issues, all the checks passed ✅ with<a href="https://github.com/EngineerDanny/Rperform/actions/runs/2544889102"><code class="language-plaintext highlighter-rouge">Check-RPerform #11</code></a> workflow run.</p> <h2 id="conclusion">CONCLUSION</h2> <p>During my tests, I realized the cause of the inconsistencies in my workflow results. When running <code class="language-plaintext highlighter-rouge">R CMD Check</code> locally, I noticed that if your internet network is slow, because the dependencies and other stuffs can not be downloaded, the test will pass with no warnings or errors. This may be a flaw in the <code class="language-plaintext highlighter-rouge">R CMD Check</code> tool. It can lead to false positives. The main reason why I didn’t notice the mistakenly created file locally was because I was on another branch (<code class="language-plaintext highlighter-rouge">test-pkg</code>) instead of the main branch (<code class="language-plaintext highlighter-rouge">master</code>). The file was rather created on the <code class="language-plaintext highlighter-rouge">master</code> branch.</p> <p><code class="language-plaintext highlighter-rouge">R CMD Checks</code> are very crucial to the success of a package especially when the package is to be published on <a href="https://cran.r-project.org">CRAN</a>. When a package passes the checks with no errors, warnings and notes, there would be no need for human intervention before the package is published on <a href="https://cran.r-project.org">CRAN</a>.</p>]]></content><author><name></name></author><category term="rperform"/><category term="test"/><category term="r"/><summary type="html"><![CDATA[Testing and Debugging Rperform to ensure that R CMD Check runs successfully]]></summary></entry><entry><title type="html">Updating the dependencies in Rperform.</title><link href="https://engineerdanny.github.io/blog/2022/Updating-dependencies-In-Rperform/" rel="alternate" type="text/html" title="Updating the dependencies in Rperform."/><published>2022-06-20T00:00:00+00:00</published><updated>2022-06-20T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Updating-dependencies-In-Rperform</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Updating-dependencies-In-Rperform/"><![CDATA[<h1 id="introduction">Introduction</h1> <p>In R, it is the main purpose of the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file to convey the metadata about a package. It is also needed to list all the dependencies that the package uses. Inside the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file, there are <code class="language-plaintext highlighter-rouge">Imports</code> and <code class="language-plaintext highlighter-rouge">Suggests</code> section under which, you can list your dependencies. There is a minor difference between the two. The packages under <code class="language-plaintext highlighter-rouge">Imports</code> are needed by your users at runtime. <code class="language-plaintext highlighter-rouge">Packages</code> under <code class="language-plaintext highlighter-rouge">Suggests</code> however, may be optional because it is either used for development or optional functionalities. There was a major issue with the major dependencies used by <code class="language-plaintext highlighter-rouge">Rperform</code>. The issue was that, the versions of the dependencies used were too old and one of the them was discontinued.</p> <h2 id="the-git2r-package">The git2r package</h2> <p>The <code class="language-plaintext highlighter-rouge">git2r</code> package is a popular R package which is mainly known for using git with R. It gives users programmatic experience with git using R. It is very fast because it implements git core methods developed with C. As the developers of the package improved and updated the package, they made a breaking transition. They made a change in support from S4 objects to S3 objects. A simple fix to this issue will be to pin the version of the package to specific versions in the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file. However, a lot of developers have always install the latest versions of packages. As I tested <code class="language-plaintext highlighter-rouge">Rperform</code> for the first time, I had the issue. This is the error I had :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">plot_metrics</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-join.r"</span><span class="p">,</span><span class="w"> </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">2</span><span class="p">,</span><span class="w"> </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">,</span><span class="w"> </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">)</span><span class="w">
</span><span class="n">Error</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">base</span><span class="o">::</span><span class="n">substr</span><span class="p">(</span><span class="n">commit_val</span><span class="o">@</span><span class="n">summary</span><span class="p">,</span><span class="w"> </span><span class="n">start</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">stop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">15</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> 
  </span><span class="n">trying</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">get</span><span class="w"> </span><span class="n">slot</span><span class="w"> </span><span class="s2">"summary"</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">object</span><span class="w"> </span><span class="p">(</span><span class="n">class</span><span class="w"> </span><span class="s2">"git_commit"</span><span class="p">)</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">S4</span><span class="w"> </span><span class="n">object</span><span class="w"> 
</span></code></pre></div></div> <p>Analyzing the error message suggests that the program is trying to get a property from an object which is not S4 object but rather S3 object. The actual issue was that my <code class="language-plaintext highlighter-rouge">git2r</code> version was the latest version. For some reason, the package version which should have been pinned to be <code class="language-plaintext highlighter-rouge">&lt;= version 0.21.0</code> was ignored by my program. The fact is that, the latest <code class="language-plaintext highlighter-rouge">git2r</code> package has a lot of new features and fixes. The first task I had to do was updating Rperform to also support the newer versions of <code class="language-plaintext highlighter-rouge">git2r</code> so as to make it easier for other developers to use and test the package. I updated the <code class="language-plaintext highlighter-rouge">git2r</code> version to <code class="language-plaintext highlighter-rouge">(&gt;= 0.30.1)</code> in the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file so it made some functions in the code obsolete. First of all, the names of some functions were updated. Refactoring the code was not difficult but running through the documentation of the <code class="language-plaintext highlighter-rouge">git2r</code> package and checking the newer functions proved to be a little challenging and time consuming. First major change I had to make was replace the <code class="language-plaintext highlighter-rouge">head</code> function to <code class="language-plaintext highlighter-rouge">repository_head</code> function. This function basically gets the <code class="language-plaintext highlighter-rouge">HEAD</code> of a repository.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># From</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">repo_head</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">git2r</span><span class="o">::</span><span class="n">head</span><span class="p">(</span><span class="n">repo</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># To</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">repo_head</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">git2r</span><span class="o">::</span><span class="n">repository_head</span><span class="p">(</span><span class="n">repo</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p>Also, I had to check all the functions related to the issue to be compatible to S3 objects. Just to name a few, some of them are :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># From</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">base</span><span class="o">::</span><span class="n">substr</span><span class="p">(</span><span class="n">commit_val</span><span class="o">@</span><span class="n">summary</span><span class="p">,</span><span class="w"> </span><span class="n">start</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">stop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">15</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">repo_head</span><span class="o">@</span><span class="n">name</span><span class="w">
</span></code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># To</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">base</span><span class="o">::</span><span class="n">substr</span><span class="p">(</span><span class="n">commit_val</span><span class="o">$</span><span class="n">summary</span><span class="p">,</span><span class="w"> </span><span class="n">start</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="n">stop</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">15</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">repo_head</span><span class="o">$</span><span class="n">name</span><span class="w">
</span></code></pre></div></div> <p>Initially, I used numeric indexes to reference list members. I switched to using named reference approach to reference list members by names instead of numeric indexes because it was less error prone. With most of the changes just like above examples, I just had to replace the <code class="language-plaintext highlighter-rouge">@</code> symbol with the <code class="language-plaintext highlighter-rouge">$</code> symbol. Others were a little more complex than that.</p> <h2 id="the-animint-dependency">The Animint dependency</h2> <p>The <a href="https://github.com/tdhock/animint">animint</a> package is a forked version of the <code class="language-plaintext highlighter-rouge">ggplot2</code> with improved features. It enables developers to design multi-plot, multi-layer, interactive and animated data visualizations. Unfortunately, the original version has been discontinued. Even though, it was an optional package in the root <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file, it was worth looking into. However, my attention only drew to it when I was running a <code class="language-plaintext highlighter-rouge">CMD R Check</code> on the <code class="language-plaintext highlighter-rouge">Rperform</code> package and it failed. The Github CI test showed that it is not possible to install it because it could not recognize the package. After digging into the issue, I realized the package has been discontinued. Fast forward, there is an updated version called the <a href="https://github.com/tdhock/animint2">animint2</a> which comes with easier installation and better syntax. Therefore I updated the package to <code class="language-plaintext highlighter-rouge">animint2</code> in the <code class="language-plaintext highlighter-rouge">DESCRIPTION</code> file. Then, I checked and tested all the functions that depend on the animint2 package. Most of them had to do with just replacing <code class="language-plaintext highlighter-rouge">animint</code> with <code class="language-plaintext highlighter-rouge">animint2</code>.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># From</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">animint</span><span class="o">::</span><span class="n">theme_animint</span><span class="p">(</span><span class="n">height</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">700</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">animint</span><span class="o">::</span><span class="n">animint2dir</span><span class="p">(</span><span class="n">plot.list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">viz.list</span><span class="p">,</span><span class="w"> </span><span class="n">out.dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">paste0</span><span class="p">(</span><span class="n">basename</span><span class="p">(</span><span class="n">getwd</span><span class="p">()),</span><span class="w"> </span><span class="s2">"_"</span><span class="p">,</span><span class="w"> </span><span class="s2">"time_animint"</span><span class="p">))</span><span class="w">
</span></code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># To</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">animint2</span><span class="o">::</span><span class="n">theme_animint</span><span class="p">(</span><span class="n">height</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">700</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">animint2</span><span class="o">::</span><span class="n">animint2dir</span><span class="p">(</span><span class="n">plot.list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">viz.list</span><span class="p">,</span><span class="w"> </span><span class="n">out.dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">paste0</span><span class="p">(</span><span class="n">basename</span><span class="p">(</span><span class="n">getwd</span><span class="p">()),</span><span class="w"> </span><span class="s2">"_"</span><span class="p">,</span><span class="w"> </span><span class="s2">"time_animint"</span><span class="p">))</span><span class="w">
</span></code></pre></div></div> <h2 id="fix-dependency-and-related-issues">Fix dependency and related issues</h2> <p>After all the changes and updates, I opened a Pull Request to address the issues. <a href="https://github.com/EngineerDanny/Rperform/pull/2">PR#2</a> and <a href="https://github.com/EngineerDanny/Rperform/pull/3">PR#3</a>. As it was a pending issue raised twice on the main repository. These combined <a href="https://github.com/analyticalmonk/Rperform/pull/47">PRs</a> close issues <a href="https://github.com/analyticalmonk/Rperform/issues/44">#44</a> and <a href="https://github.com/analyticalmonk/Rperform/issues/45">#45</a>.</p> <h1 id="conclusion">Conclusion</h1> <p>I have realized that the dependencies that our projects utilize are very crucial to the development of the package and its users. At first, I nearly gave up on the <code class="language-plaintext highlighter-rouge">Rperform</code> package because of it’s support for old dependencies which were not already installed and for some reason could not get installed on my computer. Updating dependencies ensures the package gets access to the latest features, improvements and bug fixes. Downgrading the <code class="language-plaintext highlighter-rouge">git2r</code> dependency was a temporal fix, updating and ensuring that all related issues are fixed became the permanent fix.</p>]]></content><author><name></name></author><category term="Rperform"/><category term="performance"/><category term="test"/><category term="r"/><category term="git"/><category term="github"/><summary type="html"><![CDATA[This is the total review of how I went about in fixing the issues with dependencies in Rperform package.]]></summary></entry><entry><title type="html">Fixes to some of the compilation errors of Rperform</title><link href="https://engineerdanny.github.io/blog/2022/Rperform-Compilation-Errors-And-Fixes/" rel="alternate" type="text/html" title="Fixes to some of the compilation errors of Rperform"/><published>2022-06-13T00:00:00+00:00</published><updated>2022-06-13T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Rperform-Compilation-Errors-And-Fixes</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Rperform-Compilation-Errors-And-Fixes/"><![CDATA[<h2 id="abstract">ABSTRACT</h2> <p>The main goal of the RPerform library is to make performance tests on R packages easier with GitHub. However, currently, the initial version of the RPerform library is outdated in the sense that you would need to improvise before you attempt to test RPerform. This article explains all the potential errors, issues and bugs you might encounter and how to solve them before you run the package.</p> <p>The test package that is used to test the <code class="language-plaintext highlighter-rouge">Rperform</code> library is the <code class="language-plaintext highlighter-rouge">stringr</code> (https://github.com/tdhock/stringr) package. Installation of the library has been discussed in the previous articles. Use the <code class="language-plaintext highlighter-rouge">library(Rperform)</code> command to load the library. The following command initializes the library by setting the working directory.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">setwd</span><span class="p">(</span><span class="n">dir</span><span class="o">=</span><span class="w"> </span><span class="s2">"/Users/newuser/Projects/RProjects/stringr"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <h2 id="directory-issues">DIRECTORY ISSUES</h2> <h3 id="--working-directory-error"><strong>- Working directory error</strong></h3> <p>The first error which might be thrown is :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Error</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">setwd</span><span class="p">(</span><span class="n">dir</span><span class="o">=</span><span class="w"> </span><span class="s2">"/Users/newuser/Projects/RProjects/stringe"</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w">
 </span><span class="n">cannot</span><span class="w"> </span><span class="n">change</span><span class="w"> </span><span class="n">working</span><span class="w"> </span><span class="n">directory</span><span class="w">
</span></code></pre></div></div> <p>The <code class="language-plaintext highlighter-rouge">dir</code> argument must be set to the directory of the package or project you want to test.</p> <h3 id="--test-join-directory-error"><strong>- <code class="language-plaintext highlighter-rouge">test-join</code> directory error</strong></h3> <p>There has been an update with the <code class="language-plaintext highlighter-rouge">stringr</code> repository. <code class="language-plaintext highlighter-rouge">test-join.r</code> is not in the <code class="language-plaintext highlighter-rouge">tests/testthat</code> directory. The new directory is <code class="language-plaintext highlighter-rouge">inst/tests/test-join.r</code> . Also, all the files in <code class="language-plaintext highlighter-rouge">inst/tests/</code> directory must be taken note. Misrepresenting them will result in errors. Hence, this implies that running :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_metrics</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-join.r"</span><span class="p">,</span><span class="w"> </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">,</span><span class="w"> </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p>will throw the error :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Error</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">file</span><span class="p">(</span><span class="n">con</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="s2">"r"</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w">
    </span><span class="n">cannot</span><span class="w"> </span><span class="n">open</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="s2">"tests/testthat/test-join.r"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">No</span><span class="w"> </span><span class="n">such</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">or</span><span class="w"> </span><span class="n">directory</span><span class="w">    
</span></code></pre></div></div> <p>Instead, run :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_metrics</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"inst/tests/test-join.r"</span><span class="p">,</span><span class="w"> </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">,</span><span class="w"> </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">)</span><span class="w">

</span></code></pre></div></div> <h2 id="missing-packages">MISSING PACKAGES</h2> <p>These are the packages that <code class="language-plaintext highlighter-rouge">Rperform</code> depends on. Not having it pre-installed may prevent you from running the package. We proceed by discussing the relevant dependencies and how to install them.</p> <p><code class="language-plaintext highlighter-rouge">git2r</code> : The git2r package gives developers access to Git repositories from R. The package uses the <code class="language-plaintext highlighter-rouge">libgit2</code> library which is a C implementation of the Git core methods. Therefore it allows developers to write native speed custom Git applications in any language that supports C bindings.</p> <p>To install the development version of git2r. You can use :</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">install.packages</span><span class="p">(</span><span class="s2">"git2r"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p>it’s easiest to use the devtools package:</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># install.packages("devtools")</span><span class="w">
</span><span class="n">library</span><span class="p">(</span><span class="n">devtools</span><span class="p">)</span><span class="w">
</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"ropensci/git2r"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">ggplot2</code> : The <code class="language-plaintext highlighter-rouge">ggplot2</code> is an R package used for plotting graphs. It provides useful commands that helps to create complex plots from data in a data frame. It enables quality plots to be created with minimal coding, tweaking and adjustments. The package is therefore necessary for <code class="language-plaintext highlighter-rouge">Rperform</code> to visualize performance metrics. It provides an interface for determining what variables to plot and how they are shown to the user. Organized data saves massive time when using the package to make figures.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># The easiest way to get ggplot2 is to install the whole tidyverse:</span><span class="w">
</span><span class="n">install.packages</span><span class="p">(</span><span class="s2">"tidyverse"</span><span class="p">)</span><span class="w">

</span><span class="c1"># Alternatively, install just ggplot2:</span><span class="w">
</span><span class="n">install.packages</span><span class="p">(</span><span class="s2">"ggplot2"</span><span class="p">)</span><span class="w">

</span><span class="c1"># Or the development version from GitHub:</span><span class="w">
</span><span class="n">install.packages</span><span class="p">(</span><span class="s2">"devtools"</span><span class="p">)</span><span class="w">
</span><span class="n">devtools</span><span class="o">::</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"tidyverse/ggplot2"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <h2 id="conclusion">CONCLUSION</h2> <p>It is very crucial to adequately set up the package for testing. Some of the errors have been discussed and solutions have also been proposed. It is advisable to always follow the documentation for latest the updates.</p>]]></content><author><name></name></author><category term="rperform"/><category term="test"/><category term="r"/><summary type="html"><![CDATA[Fixes to some of the compilation errors of Rperform]]></summary></entry><entry><title type="html">Testing Touchstone with a simple For Loop</title><link href="https://engineerdanny.github.io/blog/2022/Touchstone-Test-1/" rel="alternate" type="text/html" title="Testing Touchstone with a simple For Loop"/><published>2022-06-02T00:00:00+00:00</published><updated>2022-06-02T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Touchstone-Test-1</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Touchstone-Test-1/"><![CDATA[<h3 id="introduction">Introduction</h3> <p>I did a minimal testing of touchstone by using a simple <code class="language-plaintext highlighter-rouge">for</code> loop. Therefore, I created a simple R package repository on GitHub called <a href="https://github.com/EngineerDanny/TouchTest">TouchTest</a> . Inside the <code class="language-plaintext highlighter-rouge">script.R</code> file, there exists a function <code class="language-plaintext highlighter-rouge">touchstone::benchmark_run</code> which helps to benchmark any function call from the package.</p> <p>To make it simple to test the minimal functionality of <code class="language-plaintext highlighter-rouge">touchstone</code>, I modified the function and wrote the <code class="language-plaintext highlighter-rouge">for</code> loop inside a <code class="language-plaintext highlighter-rouge">random_test</code> function.</p> <h3 id="test">Test</h3> <p>On the <code class="language-plaintext highlighter-rouge">main</code> branch, inside the <code class="language-plaintext highlighter-rouge">script.R</code> file, we basically loop from 1 to 10 printing the current number.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># benchmark a function call from your package (two calls per branch)</span><span class="w">
</span><span class="n">touchstone</span><span class="o">::</span><span class="n">benchmark_run</span><span class="p">(</span><span class="w">
  </span><span class="c1"># expr_before_benchmark = source("dir/data.R"), #&lt;-- TODO OTPIONAL setup before benchmark</span><span class="w">
  </span><span class="n">random_test</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">print</span><span class="p">(</span><span class="s2">"Hello, world!"</span><span class="p">)</span><span class="w">
    </span><span class="c1"># Loop from 1 to 10</span><span class="w">
    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">1</span><span class="o">:</span><span class="m">10</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">},</span><span class="w"> </span><span class="c1">#&lt;- TODO put the call you want to benchmark here</span><span class="w">
  </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p>However, onn the <code class="language-plaintext highlighter-rouge">devel</code> branch, there is a minor change in the for loop. We print from 1 to 100 instead.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># benchmark a function call from your package (two calls per branch)</span><span class="w">
</span><span class="n">touchstone</span><span class="o">::</span><span class="n">benchmark_run</span><span class="p">(</span><span class="w">
  </span><span class="c1"># expr_before_benchmark = source("dir/data.R"), #&lt;-- TODO OTPIONAL setup before benchmark</span><span class="w">
  </span><span class="n">random_test</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">print</span><span class="p">(</span><span class="s2">"Hello, world!"</span><span class="p">)</span><span class="w">
    </span><span class="c1"># Loop from 1 to 100</span><span class="w">
    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">1</span><span class="o">:</span><span class="m">100</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="n">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">},</span><span class="w"> </span><span class="c1">#&lt;- TODO put the call you want to benchmark here</span><span class="w">
  </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">2</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <h3 id="results">Results</h3> <p>It is quite obvious that the <code class="language-plaintext highlighter-rouge">1 to 100 loop</code> will take longer time than the <code class="language-plaintext highlighter-rouge">1 to 10 loop</code>. Inside the <code class="language-plaintext highlighter-rouge">touchstone</code> directory, <code class="language-plaintext highlighter-rouge">plots</code> and <code class="language-plaintext highlighter-rouge">pr-comment</code> folders are created naturally containing the image of the plot and the PR comment text respectively. Below shows the results as expected.</p> <p><img src="https://raw.githubusercontent.com/EngineerDanny/GSOC22-RPerform-Blog/master/images/for-loop-touch-test.png" alt="time plot" title="Time Plot"/></p> <p>The graph above demonstrates the visualizations of the distribution of the timings for both branches. It can be inferred from the graph above that the density of the <code class="language-plaintext highlighter-rouge">devel</code> branch is greater than that of the <code class="language-plaintext highlighter-rouge">main</code> branch. This is due to the fact that the <code class="language-plaintext highlighter-rouge">devel</code> branch entails looping 100 times whereas the <code class="language-plaintext highlighter-rouge">main</code> branch entails looping just 10 times.</p> <p>Benchmark result is posted as a comment in the Pull Request. An example is shown below :</p> <hr/> <p>This is how benchmark results would change (along with a 95% confidence interval in relative change) if <code class="language-plaintext highlighter-rouge">b61b5addb59ac69eca91ee97caf7e5f5ef986aed</code> is merged into main:</p> <ul> <li>  :ballot_box_with_check:random_test: 1.24µs -&gt; 1.3µs [-5.9%, +15.17%] Further explanation regarding interpretation and methodology can be found in the <a href="https://lorenzwalthert.github.io/touchstone/articles/inference.html">documentation</a>.</li> </ul> <hr/> <p>The results can be interpreted as an increase in time by approximately 15.17% from the <code class="language-plaintext highlighter-rouge">devel</code> branch when compared to the <code class="language-plaintext highlighter-rouge">main</code> branch. To avoid any uncertainties, under the hood, the code is run <code class="language-plaintext highlighter-rouge">n</code> times based on the confidence interval. The confidence interval shows the certainties about any estimated differences. Hence, a 0.95 confidence interval tells that if the benchmarking experiment were to be repeated 100 times, the estimated change in speed would be in the interval 95 out of 100 times. The graph generally gets noisy when there is no significant speed change.</p> <p>Therefore, merging a Pull Request of such nature will mean that the code will be a little bit slower. However, checking from the speed decrease implies that it will hardly be noticed practically. There is always a trade-off between time and functionality especially when a new feature is introduced in a code. This is the reason why the Confidence Interval is very crucial with regards to code benchmarking.</p> <h3 id="conclusion">Conclusion</h3> <p>Even though, the <code class="language-plaintext highlighter-rouge">touchstone</code> package is an experimental R package, it aims on providing the means to perform accurate benchmarking tests for package developers. Due to the fact that Pull requests are natural units for measuring speed, connecting benchmarking to pull requests makes it easier and faster to use.</p>]]></content><author><name></name></author><category term="touchstone"/><category term="test"/><category term="r"/><category term="git"/><category term="github"/><summary type="html"><![CDATA[A minimal testing of touchstone by using a simple for loop]]></summary></entry><entry><title type="html">Reviewing The Touchstone R Package</title><link href="https://engineerdanny.github.io/blog/2022/Touchstone-Review/" rel="alternate" type="text/html" title="Reviewing The Touchstone R Package"/><published>2022-06-01T00:00:00+00:00</published><updated>2022-06-01T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/Touchstone-Review</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/Touchstone-Review/"><![CDATA[<h2 id="1-introduction">1. Introduction</h2> <p><a href="https://github.com/lorenzwalthert/touchstone"><code class="language-plaintext highlighter-rouge">Touchstone</code></a> is an R tool which provides accurate benchmarking features for testing other R packages. It provides continuous benchmarking with reliable relative measurement and uncertainty reporting. <strong>It is enriched with features which are very useful especially with respect to merging a Pull Request into target branch.</strong> Therefore, it is integrated with GitHub Continuous Integration(CI) which helps to automate the whole process.</p> <h2 id="2-concept">2. Concept</h2> <p>For your PR branch and the target branch, <a href="https://github.com/lorenzwalthert/touchstone"><code class="language-plaintext highlighter-rouge">touchstone</code></a> will : <br/></p> <ul> <li>build two versions of the package in isolated libraries.</li> <li>measure the accurate relative differences between the branches. The code under experimentation will be run several times in a random order.</li> <li>comment the results of the benchmarking on the Pull Request.</li> <li>create visualizations to demonstrate the distribution of the timings for both branches.</li> </ul> <h2 id="3-installation">3. Installation</h2> <p>Installation can be done in two ways : <br/></p> <ul> <li><strong>CRAN</strong> : <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">install.packages</span><span class="p">(</span><span class="s2">"touchstone"</span><span class="p">)</span><span class="w">
</span></code></pre></div> </div> </li> <li><strong>GitHub</strong> : <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="n">devtools</span><span class="o">::</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"lorenzwalthert/touchstone"</span><span class="p">)</span><span class="w">
</span></code></pre></div> </div> </li> </ul> <h2 id="4-package-usage">4. Package Usage</h2> <p>Initialize touchstone by running <br/></p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">touchstone</span><span class="o">::</span><span class="n">use_touchstone</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <p>The above line of code will :</p> <ul> <li> <p>Create a directory known as the <code class="language-plaintext highlighter-rouge">touchstone</code> directory in the root of the repository with <code class="language-plaintext highlighter-rouge">config.json</code> and <code class="language-plaintext highlighter-rouge">script.R</code>. The <code class="language-plaintext highlighter-rouge">config.json</code> contains configurations that define how to run your benchmark. The <code class="language-plaintext highlighter-rouge">script.R</code> is the script that runs the benchmark. The <code class="language-plaintext highlighter-rouge">header.R</code> contains the default PR header whilst the <code class="language-plaintext highlighter-rouge">footer.R</code> containing the default PR comment footer.</p> </li> <li> <p>Populate the file <code class="language-plaintext highlighter-rouge">touchstone-receive.yaml</code> in <code class="language-plaintext highlighter-rouge">.github/workflows/.</code> and <code class="language-plaintext highlighter-rouge">touchstone-comment.yaml</code> in <code class="language-plaintext highlighter-rouge">.github/workflows/</code> respectively.</p> </li> <li> <p>Add the <code class="language-plaintext highlighter-rouge">touchstone</code> directory to <code class="language-plaintext highlighter-rouge">.Rbuildignore</code> file in the root directory of your repository.</p> </li> </ul> <p>Write the workflow files you need to invoke <code class="language-plaintext highlighter-rouge">touchstone</code> in new pull requests into <code class="language-plaintext highlighter-rouge">.github/workflows/</code>.</p> <p>Modify the <code class="language-plaintext highlighter-rouge">touchstone</code> script <code class="language-plaintext highlighter-rouge">touchstone/script.R</code> to run different benchmarks.</p> <h2 id="5-understanding-the-script">5. Understanding the script</h2> <p>There are three default functions inside the <code class="language-plaintext highlighter-rouge">script.R</code> file.</p> <h3 id="i-branch_install">(i) <code class="language-plaintext highlighter-rouge">branch_install</code></h3> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">touchstone</span><span class="o">::</span><span class="n">branch_install</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">branch_install</code> installs each <code class="language-plaintext highlighter-rouge">branch</code> in a separate library for isolation.</p> <h4 id="usage">Usage</h4> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">branch_install</span><span class="p">(</span><span class="w">
  </span><span class="n">branches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_BASE_REF"</span><span class="p">),</span><span class="w">
    </span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_HEAD_REF"</span><span class="p">)),</span><span class="w">
  </span><span class="n">path_pkg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"."</span><span class="p">,</span><span class="w">
  </span><span class="n">install_dependencies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><strong>The arguments :</strong> <br/> <code class="language-plaintext highlighter-rouge">branches</code> are names of the branches in character vector <br/> <code class="language-plaintext highlighter-rouge">path_pkg</code> represents the path to the package which has a default value of <code class="language-plaintext highlighter-rouge">"."</code> <br/> <code class="language-plaintext highlighter-rouge">install_dependencies</code> is a boolean which enables dependencies to be installed, has a default value of <code class="language-plaintext highlighter-rouge">FALSE</code> <br/></p> <h3 id="ii-benchmark_run">(ii) <code class="language-plaintext highlighter-rouge">benchmark_run</code></h3> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">touchstone</span><span class="o">::</span><span class="n">benchmark_run</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">benchmark_run</code> runs benchmarks for git branches using function calls from your package.</p> <h4 id="usage-1">Usage</h4> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">benchmark_run</span><span class="p">(</span><span class="w">
  </span><span class="n">expr_before_benchmark</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">},</span><span class="w">
  </span><span class="n">...</span><span class="p">,</span><span class="w">
  </span><span class="n">branches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_BASE_REF"</span><span class="p">),</span><span class="w">
    </span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_HEAD_REF"</span><span class="p">)),</span><span class="w">
  </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">100</span><span class="p">,</span><span class="w">
  </span><span class="n">path_pkg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"."</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><strong>The arguments :</strong> <br/> <code class="language-plaintext highlighter-rouge">expr_before_benchmark</code> allows an expression to be executed just before benchmark is run<br/> <code class="language-plaintext highlighter-rouge">...</code> is the named expression of length one with code to benchmark<br/> <code class="language-plaintext highlighter-rouge">branches</code> are names of the branches in character vector <br/> <code class="language-plaintext highlighter-rouge">n</code> is the number of times benchmarks should be run for each of the branches. <br/> <code class="language-plaintext highlighter-rouge">path_pkg</code> represents the path to the package <br/></p> <h3 id="ii-benchmark_analyze">(ii) <code class="language-plaintext highlighter-rouge">benchmark_analyze</code></h3> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">touchstone</span><span class="o">::</span><span class="n">benchmark_analyze</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">benchmark_analyze</code> creates artifacts used downstream in the GitHub Action to turn raw benchmark results into text and figures.</p> <h4 id="usage-2">Usage</h4> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">benchmark_analyze</span><span class="p">(</span><span class="w">
  </span><span class="n">branches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_BASE_REF"</span><span class="p">),</span><span class="w">
    </span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_HEAD_REF"</span><span class="p">)),</span><span class="w">
  </span><span class="n">names</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">NULL</span><span class="p">,</span><span class="w">
  </span><span class="n">ci</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0.95</span><span class="w">
</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><strong>The arguments :</strong> <br/> <code class="language-plaintext highlighter-rouge">branches</code> are the names of the branches in character vector under consideration <br/> <code class="language-plaintext highlighter-rouge">names</code> are the names of the branches which is actually used for the analysis. <br/> <code class="language-plaintext highlighter-rouge">ci</code> represents the confidence level which defaults to 0.95 out of 1 <br/></p> <h2 id="6-running-the--script">6. Running the script</h2> <p>On the R Interactive console, run</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">touchstone</span><span class="o">::</span><span class="n">run_script</span><span class="p">()</span><span class="w">
</span></code></pre></div></div> <h4 id="usage-3">Usage</h4> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">run_script</span><span class="p">(</span><span class="w">
  </span><span class="n">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"touchstone/script.R"</span><span class="p">,</span><span class="w">
  </span><span class="n">branch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">branch_get_or_fail</span><span class="p">(</span><span class="s2">"GITHUB_HEAD_REF"</span><span class="p">)</span><span class="w">
</span><span class="p">)</span><span class="w">

</span></code></pre></div></div> <p><strong>The arguments :</strong> <br/> <code class="language-plaintext highlighter-rouge">path</code> is the path to the script to run <br/> <code class="language-plaintext highlighter-rouge">branch</code> is the name of the branch corresponding to the library <br/> <br/></p> <p>After committing and pushing the workflow files to default branch, <code class="language-plaintext highlighter-rouge">Github CI</code> will run the benchmarks on every pull request and on each commit while that pull request is open.</p>]]></content><author><name></name></author><category term="touchstone"/><category term="test"/><category term="r"/><category term="git"/><category term="github"/><summary type="html"><![CDATA[An in-depth review of touchstone, an R tool for benchmarking performance of code]]></summary></entry><entry><title type="html">Sample RPerform package usage</title><link href="https://engineerdanny.github.io/blog/2022/RPerform/" rel="alternate" type="text/html" title="Sample RPerform package usage"/><published>2022-05-24T00:00:00+00:00</published><updated>2022-05-24T00:00:00+00:00</updated><id>https://engineerdanny.github.io/blog/2022/RPerform</id><content type="html" xml:base="https://engineerdanny.github.io/blog/2022/RPerform/"><![CDATA[<h1 id="introduction">Introduction</h1> <p><code class="language-plaintext highlighter-rouge">Rperform</code> is a package that allows R developers to track quantitative performance metrics of their code. It helps to provide changes in a package’s performance metrics related to runtime and memory. It is used to access performance metrics over different git versions and across git branches. It can also be integrated with <code class="language-plaintext highlighter-rouge">Travis-CI</code> for performance testing during Travis builds by making changes to the repo’s <code class="language-plaintext highlighter-rouge">.travis.yml</code> file. It can prove to be particularly useful while measuring the possible changes which can be introduced by a pull request (PR).</p> <p><em>The project was initiated as a part of the <a href="https://github.com/rstats-gsoc/gsoc2015/wiki/Test-timings-on-Travis">Google Summer of Code 2015</a> program and was accepted into the <a href="https://github.com/rstats-gsoc/gsoc2016/wiki/Rperform:-Performance-analysis-of-R-package-code">Google Summer of Code 2016</a> program.</em></p> <h1 id="installation">Installation</h1> <ul> <li>You can install the package from github using :</li> </ul> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">library</span><span class="p">(</span><span class="n">devtools</span><span class="p">)</span><span class="w">
</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"analyticalmonk/Rperform"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p>or</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">devtools</span><span class="o">::</span><span class="n">install_github</span><span class="p">(</span><span class="s2">"analyticalmonk/Rperform"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <h1 id="basic-examples">Basic examples</h1> <p><strong>NOTE</strong>: The Rperform package requires you to set the current directory to the concerned git repository before using the functions.</p> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">setwd</span><span class="p">(</span><span class="n">dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Path/to/repo"</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <ul> <li>The following example illustrates the use of the <code class="language-plaintext highlighter-rouge">Rperform::plot_metrics()</code> function on the git repository of the package <a href="https://github.com/tdhock/stringr">stringr</a>.</li> </ul> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">setwd</span><span class="p">(</span><span class="s2">"./stringr"</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">library</span><span class="p">(</span><span class="n">Rperform</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">plot_metrics</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-join.r"</span><span class="p">,</span><span class="w"> </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"time"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">,</span><span class="w"> </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><img src="https://raw.githubusercontent.com/EngineerDanny/GSOC22-RPerform-Blog/master/images/Rplot_time.jpeg" alt="time plot" title="Time Plot"/></p> <ul> <li>The following example illustrates the use of the <code class="language-plaintext highlighter-rouge">Rperform::plot_branchmetrics()</code> function on the git repository of the package <a href="https://github.com/tdhock/stringr">stringr</a>.</li> </ul> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">setwd</span><span class="p">(</span><span class="s2">"./stringr"</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">library</span><span class="p">(</span><span class="n">Rperform</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">plot_branchmetrics</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"tests/testthat/test-interp.r"</span><span class="p">,</span><span class="w"> </span><span class="n">metric</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"memory"</span><span class="p">,</span><span class="w"> </span><span class="n">branch1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"rperform_test"</span><span class="p">,</span><span class="w"> </span><span class="n">branch2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"master"</span><span class="p">,</span><span class="w"> </span><span class="n">save_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">F</span><span class="p">,</span><span class="w"> </span><span class="n">save_plots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">F</span><span class="p">)</span><span class="w">
</span></code></pre></div></div> <p><img src="https://raw.githubusercontent.com/EngineerDanny/GSOC22-RPerform-Blog/master/images/Rplot_branchmem.jpeg" alt="memory plot" title="Memory Plot"/></p> <ul> <li>The following example illustrates the use of the <code class="language-plaintext highlighter-rouge">Rperform::time_compare()</code> and <code class="language-plaintext highlighter-rouge">Rperform::mem_compare()</code> functions on the git repository of the package <a href="https://github.com/tdhock/stringr">stringr</a>.</li> </ul> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">setwd</span><span class="p">(</span><span class="s2">"./stringr"</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">library</span><span class="p">(</span><span class="n">Rperform</span><span class="p">)</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> </span><span class="n">time_compare</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"./tests/testthat/test-dup.r"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">2</span><span class="p">)</span><span class="w">
                          </span><span class="n">test_name</span><span class="w"> </span><span class="n">metric_name</span><span class="w"> </span><span class="n">status</span><span class="w">  </span><span class="n">metric_val</span><span class="w">         </span><span class="n">msg_val</span><span class="w">           </span><span class="n">date_time</span><span class="w">
</span><span class="m">1</span><span class="w">           </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001797014</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">2</span><span class="w">           </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001539050</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">3</span><span class="w">           </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001545034</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">4</span><span class="w">  </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001019430</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">5</span><span class="w">  </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.000784386</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">6</span><span class="w">  </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.000766279</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">7</span><span class="w">                        </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003555478</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">8</span><span class="w">                        </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003118946</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">9</span><span class="w">                        </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003106017</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">10</span><span class="w">          </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001780849</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">11</span><span class="w">          </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001545568</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">12</span><span class="w">          </span><span class="n">basic</span><span class="w"> </span><span class="n">duplication</span><span class="w"> </span><span class="n">works</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001517300</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">13</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.001028882</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">14</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.000783847</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">15</span><span class="w"> </span><span class="m">0</span><span class="w"> </span><span class="n">duplicates</span><span class="w"> </span><span class="n">equals</span><span class="w"> </span><span class="n">empty</span><span class="w"> </span><span class="n">string</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.000771520</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">16</span><span class="w">                       </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003436051</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">17</span><span class="w">                       </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003130397</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="m">18</span><span class="w">                       </span><span class="n">test</span><span class="o">-</span><span class="n">dup.r</span><span class="w">        </span><span class="n">time</span><span class="w">   </span><span class="n">pass</span><span class="w"> </span><span class="m">0.003082713</span><span class="w"> </span><span class="n">Require</span><span class="w"> </span><span class="n">latest</span><span class="w">  </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">03</span><span class="o">:</span><span class="m">37</span><span class="w">
</span><span class="o">&gt;</span><span class="w"> 
</span></code></pre></div></div> <div class="language-r highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="w"> </span><span class="n">Rperform</span><span class="o">::</span><span class="n">mem_compare</span><span class="p">(</span><span class="n">test_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"./tests/testthat/test-join.r"</span><span class="p">,</span><span class="w"> </span><span class="n">num_commits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">)</span><span class="w">
             </span><span class="n">test_name</span><span class="w"> </span><span class="n">metric_name</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="n">metric_val</span><span class="w">         </span><span class="n">msg_val</span><span class="w">           </span><span class="n">date_time</span><span class="w">
</span><span class="m">11.1</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">11.2</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">11.3</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.044</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">11.4</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.044</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">11.5</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.148</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">11.6</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.148</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.1</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.2</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.3</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.044</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.4</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.044</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.5</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.144</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">12.6</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.144</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.1</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.2</span><span class="w">  </span><span class="n">basic</span><span class="w"> </span><span class="n">case</span><span class="w"> </span><span class="n">works</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.040</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.3</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.048</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.4</span><span class="w"> </span><span class="n">NULLs</span><span class="w"> </span><span class="n">are</span><span class="w"> </span><span class="n">dropped</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.048</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.5</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">max_mem_mb</span><span class="w">   </span><span class="n">pass</span><span class="w">      </span><span class="m">0.148</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span><span class="m">13.6</span><span class="w">       </span><span class="n">test</span><span class="o">-</span><span class="n">join.r</span><span class="w">     </span><span class="n">leak_mb</span><span class="w">      </span><span class="n">pass</span><span class="w">      </span><span class="m">0.148</span><span class="w"> </span><span class="n">Can</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="n">CRA</span><span class="w"> </span><span class="m">2015-01-08</span><span class="w"> </span><span class="m">14</span><span class="o">:</span><span class="m">09</span><span class="o">:</span><span class="m">43</span><span class="w">
</span></code></pre></div></div>]]></content><author><name></name></author><category term="rperform"/><category term="test"/><category term="r"/><summary type="html"><![CDATA[A minimal example of using Rperform to track quantitative performance metrics of code]]></summary></entry></feed>