<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Tyler Hillery</title>
<link>https://www.tylerhillery.com/blog.html</link>
<atom:link href="https://www.tylerhillery.com/blog.xml" rel="self" type="application/rss+xml"/>
<description>Personal website where I share my thoughts, ideas and projects.</description>
<image>
<url>https://www.tylerhillery.com/assets/images/profile2.jpg</url>
<title>Tyler Hillery</title>
<link>https://www.tylerhillery.com/blog.html</link>
</image>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Sat, 21 Mar 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Monitoring PgBouncer Client Connections</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/monitoring-pgbouncer-client-connections/</link>
  <description><![CDATA[ 




<hr>
<p><a href="https://www.pgbouncer.org/">PgBouncer</a> is a connection pooler for Postgres. Postgres uses one process per connection, which can become problematic when creating large numbers of client connections. It can also be expensive to repeatedly drop and recreate these connections each time a client connects.</p>
<p>A common solution is to use a pooler that sits in front of your database. PgBouncer is one of the most popular options for Postgres. It maintains a pool of connections to Postgres that are reused across clients. Clients connect to PgBouncer, and from their perspective, it behaves the same as connecting directly to Postgres.</p>
<p>One of the things you might want to understand when deploying PgBouncer is the status of the various connections being made through it. This is similar to the information provided by the <a href="https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW">pg_stat_activity</a> view in Postgres.</p>
<p>PgBouncer does not provide a <code>pg_stat_activity</code> view. Instead, it offers the <a href="https://www.pgbouncer.org/usage.html#admin-console">SHOW CLIENTS</a> command, which you can run to inspect client connections. Here is an example of what that output looks like when using psql:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode sql code-with-copy"><code class="sourceCode sql"><span id="cb1-1">pgbouncer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span># SHOW CLIENTS;</span>
<span id="cb1-2"> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> |   <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">user</span>   | <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">database</span>  | replication | state  |     addr      | port  |  local_addr   | local_port |      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">connect_time</span>       |      request_time       | wait | wait_us | close_needed |      ptr       | <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span> | remote_pid | tls | application_name | prepared_statements | <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">id</span></span>
<span id="cb1-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">------+----------+-----------+-------------+--------+---------------+-------+---------------+------------+-------------------------+-------------------------+------+---------+--------------+----------------+------+------------+-----+------------------+---------------------+----</span></span>
<span id="cb1-4"> C    | postgres | pgbouncer | <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">none</span>        | active | <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">192</span>.<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">168</span>.<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">107.1</span> | <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">59281</span> | <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">192</span>.<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">168</span>.<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">107.3</span> |       <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6432</span> | <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">03</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">:35:54</span> UTC | <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2026</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">03</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">:35:57</span> UTC |    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> |       <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> |            <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> | <span class="bn" style="color: #AD0000;
background-color: null;
font-style: inherit;">0xaaaadf56c9b0</span> |      |          <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> |     | psql             |                   <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> |  <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span></code></pre></div></div>
<p>What if you want to view this information over time? That is where the <a href="https://github.com/prometheus-community/pgbouncer_exporter">Prometheus exporter for PgBouncer</a> comes in. I recently contributed a feature that collects data from the <code>SHOW CLIENTS</code> command, which was included in the 0.12.0 release. You can now use the exporter to visualize <code>SHOW CLIENTS</code> data over time.</p>
<p>The metric name is <code>pgbouncer_client_connections</code>, and it includes the labels <code>database</code>, <code>user</code>, <code>application_name</code>, and <code>state</code>. Here is an example PromQL query:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode sql code-with-copy"><code class="sourceCode sql"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">by</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">database</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">user</span>, application_name, state) (pgbouncer_client_connections)</span></code></pre></div></div>
<p>Here is an example visualization where each series here shows # of connections for each application name: <code>psql</code>, <code>app1</code>, and <code>app2</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/pgbouncer-grafana.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:100.0%"></p>
</figure>
</div>
<p>You can use my repo, <a href="https://github.com/TylerHillery/pgbouncer-show-clients-demo">pgbouncer-show-clients-demo</a> to try this out yourself.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/monitoring-pgbouncer-client-connections/</guid>
  <pubDate>Sat, 21 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries Unblocking the Event Loop</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-unblocking-the-event-loop/</link>
  <description><![CDATA[ 




<hr>
<p>I’ve been ramping up on Node.js for my new team at Supabase, and I’ve learned the first rule of Node.js club: Don’t block the event loop.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/nodejs-club.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:33.0%"></p>
</figure>
</div>
<p>I’m not going to get into the details of how the Node.js event loop works. Instead, I’ll walk through my experience debugging an issue where a library was blocking it.</p>
<div class="callout callout-style-default callout-note callout-titled" title="">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>My favorite resources to learn about the event loop:</p>
<ul>
<li><a href="https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick">Node.js Docs - The Node.js Event Loop</a></li>
<li><a href="https://blog.platformatic.dev/the-nodejs-event-loop">Platformatic - The Node.js Event Loop</a></li>
<li><a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ&amp;t=1s">What the heck is the event loop anyway? | Philip Roberts | JSConf EU</a></li>
</ul>
</div>
</div>
</div>
<p>We made a change to enable <a href="https://opentelemetry.io/">OpenTelemetry</a> using the open source npm libraries <code>@opentelemetry/*</code>. After deploying this change, our max CPU spiked to 100%. By the time I came online, a discussion was already underway with various hypotheses about the cause.</p>
<p>Coincidentally, I recently read a blog post, <a href="https://blog.platformatic.dev/introducing-next-gen-flamegraphs-for-nodejs">Introducing Next-Generating Flamegraph Visualization in Node.js</a>, and this seemed like the perfect use case for CPU profiling.</p>
<p>This isn’t my first time using flamegraphs. If you’ve read my blog post on <a href="../tyler-tries-web-dev/#oom">Tyler Tries Web Development</a>, I wrote about my experience with <a href="https://bloomberg.github.io/memray/">memray</a>, a Python memory profiler. I linked some good resources there about what they are and how to read them.</p>
<p>Here is how I set up our app for profiling:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git clone https://github.com/supabase/storage.git</span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cd storage</span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cp .env.sample .env</span>
<span id="cb1-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npm add <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> @platformatic/flame</span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npm install</span>
<span id="cb1-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npm run infra:start</span>
<span id="cb1-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx flame run <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--manual</span> dist/start/server.js</span></code></pre></div></div>
<p>I then ran a <a href="https://k6.io/">k6</a> script to generate some load on our app in a separate terminal:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> node src/test/k6/run-benchmark.cjs</span></code></pre></div></div>
<p>Once the benchmark was over, I hit <code>CTRL+C</code> to stop the profiling and exit. This produced a CPU profile: <code>cpu-profile-2026-03-20T15-59-05-224Z.pb</code>. To create the flamegraph I ran:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx flame generate cpu-profile-2026-03-04T16-04-45-113Z</span></code></pre></div></div>
<p>This produces an HTML and markdown file. Here is what the flamegraph looked like:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/node-flamegraph-01.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:100.0%"></p>
</figure>
</div>
<p>My main mental model when looking at flamegraphs is to look for the widest bottom of the flame. With this in mind, the stack frame labeled <code>spawn</code> caught my eye:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/node-flamegraph-02.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:100.0%"></p>
</figure>
</div>
<p>Going down the call stack, <code>spawn</code> is being called from <code>getDefaultNetworkInterface()</code> in <code>node_modules/systeminformation/lib/network.js</code> and it gets there via <code>execSync()</code>. Remember, the first rule of Node.js club is don’t block the event loop. Yet, here we have a synchronous call.</p>
<p>Another nice benefit of the flame tool is the markdown report it generates which confirms our interpretation of the flamegraph:</p>
<div class="callout callout-style-simple callout-note no-icon callout-titled" title="Markdown Report">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Markdown Report
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<section id="pprof-analysis-cpu" class="level3 callout-body-container callout-body">
<h3 class="anchored" data-anchor-id="pprof-analysis-cpu">PPROF Analysis: CPU</h3>
<p><strong>Profile:</strong> <code>cpu-profile-2026-03-04T16-04-45-113Z.pb</code> <strong>Duration:</strong> 452.4s | <strong>Samples:</strong> 2,156 | <strong>Type:</strong> sample (count)</p>
<section id="top-hotspots-by-self-time" class="level4">
<h4 class="anchored" data-anchor-id="top-hotspots-by-self-time">Top Hotspots (by self-time)</h4>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Rank</th>
<th>Function</th>
<th>Self%</th>
<th>Cum%</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>1</td>
<td><code>spawn</code></td>
<td>10.3%</td>
<td>10.3%</td>
<td><code>&lt;native&gt;</code></td>
</tr>
<tr class="even">
<td>2</td>
<td><code>Garbage Collection</code></td>
<td>5.8%</td>
<td>5.8%</td>
<td><code>&lt;native&gt;</code></td>
</tr>
<tr class="odd">
<td>3</td>
<td><code>runMicrotasks</code></td>
<td>2.3%</td>
<td>40.5%</td>
<td><code>&lt;native&gt;</code></td>
</tr>
<tr class="even">
<td>4</td>
<td><code>writeBuffer</code></td>
<td>1.7%</td>
<td>1.7%</td>
<td><code>&lt;native&gt;</code></td>
</tr>
<tr class="odd">
<td>5</td>
<td><code>writev</code></td>
<td>1.5%</td>
<td>1.5%</td>
<td><code>&lt;native&gt;</code></td>
</tr>
<tr class="even">
<td>6</td>
<td><code>redefineProperties</code></td>
<td>1.4%</td>
<td>1.6%</td>
<td><code>make-knex.js:240</code></td>
</tr>
<tr class="odd">
<td>7</td>
<td><code>onStreamRead</code></td>
<td>1.2%</td>
<td>13.7%</td>
<td><code>stream_base_commons:166</code></td>
</tr>
</tbody>
</table>
</section>
<section id="critical-paths-top-cumulative-chains" class="level4">
<h4 class="anchored" data-anchor-id="critical-paths-top-cumulative-chains">Critical Paths (top cumulative chains)</h4>
<ol type="1">
<li><strong>[58.3%]</strong> <code>runMicrotasks</code> → <code>ensureConnection</code> → <code>ensureConnectionCallback</code> → <code>query</code> → <code>trxClient.query</code> → <code>(anonymous:L#370:C#33)</code> → <code>query</code> → <code>executeQuery</code> → <code>_query</code> → <code>(anonymous:L#228:C#33)</code> → <code>query</code> → <code>_pulseQueryQueue</code> → <code>submit</code> → <code>Writable.uncork</code> → <code>clearBuffer</code> → <code>doWrite</code> → <code>Socket._writev</code> → <code>Socket._writeGeneric</code> → <code>writevGeneric</code> → <code>writev</code></li>
<li><strong>[13.7%]</strong> <code>Readable.push</code> → <code>readableAddChunkPushByteMode</code> → <code>addChunk</code> → <code>emit</code> → <code>(anonymous:L#11:C#23)</code> → <code>parse</code> → <code>(anonymous:L#111:C#19)</code> → <code>emit</code> → <code>_handleRowDescription</code> → <code>handleRowDescription</code> → <code>addFields</code> → <code>TypeOverrides.getTypeParser</code> → <code>getTypeParser</code></li>
<li><strong>[10.3%]</strong> <code>(anonymous:L#1267:C#22)</code> → <code>getDefaultNetworkInterface</code> → <code>execSync</code> → <code>spawnSync</code> → <code>spawnSync</code> → <code>spawn</code></li>
<li><strong>[5.8%]</strong> <code>Garbage Collection</code></li>
<li><strong>[4.8%]</strong> <code>next</code> → <code>preHandlerCallback</code> → <code>(anonymous:L#86:C#5)</code> → <code>uploadFromRequest</code> → <code>findBucketById</code> → <code>runQuery</code> → <code>(anonymous:L#131:C#12)</code> → <code>transaction</code> → <code>retry</code> → <code>run</code> → <code>RetryOperation.attempt</code> → <code>runAttempt</code> → <code>tnx.minTimeout</code> → <code>acquire</code> → <code>createKnexPool</code> → <code>knex</code> → <code>Client_PG</code> → <code>Client</code> → <code>initializeDriver</code> → <code>_driver</code> → <code>require</code> → <code>Hook._require.Module.require</code> → <code>patchedRequire</code> → <code>(anonymous:L#1335:C#35)</code> → <code>(anonymous:L#696:C#28)</code> → <code>resolveExports</code> → <code>finalizeEsmResolution</code> → <code>tryFile</code> → <code>toRealPath</code> → <code>realpathSync</code> → <code>wrappedFn</code></li>
</ol>
</section>
<section id="key-observations" class="level4">
<h4 class="anchored" data-anchor-id="key-observations">Key Observations</h4>
<ul>
<li>Native <code>spawn</code> dominates (<strong>10.3%</strong> self-time)</li>
</ul>
</section>
</section>
</div>
</div>
<p>It’s clear that <code>spawn</code> is the main culprit, accounting for 10.3% of total CPU samples.</p>
<p>Unfortunately, the flamegraph doesn’t show the full call path and stops at <code>node_modules/systeminformation/lib/network.js</code> so we have to do some grepping:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> rg <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"systeminformation/lib/network"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-u</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> </span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node_modules/@opentelemetry/host-metrics/build/src/stats/si.js.map</span></span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node_modules/@opentelemetry/host-metrics/build/src/stats/si.js</span></span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb5-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Object</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">defineProperty</span>(exports<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__esModule"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-2">exports<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">getNetworkData</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">void</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Import from the network file directly as bundlers trigger the 'osx-temperature-sensor' import in the systeminformation/lib/cpu.js,</span></span>
<span id="cb5-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// resulting in the following warning: "Can't resolve 'osx-temperature-sensor'"</span></span>
<span id="cb5-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// See https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2071</span></span>
<span id="cb5-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> network_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">require</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"systeminformation/lib/network"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getNetworkData</span>() {</span>
<span id="cb5-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Promise</span>(resolve <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> {</span>
<span id="cb5-9">        (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> network_1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">networkStats</span>)()</span>
<span id="cb5-10">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(resolve)</span>
<span id="cb5-11">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">catch</span>(() <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> {</span>
<span id="cb5-12">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">resolve</span>([])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-13">        })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-14">    })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-15">}</span>
<span id="cb5-16">exports<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">getNetworkData</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> getNetworkData<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>This confirms <code>@opentelemetry/host-metrics</code> is what’s calling into the <code>systeminformation/lib/network</code> module. This makes sense given our recent change to add OpenTelemetry. Now we just need to find where in our app we use it:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> rg <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"@opentelemetry/host-metrics"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span>   </span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">package.json</span></span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">package-lock.json</span></span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">src/internal/monitoring/otel-metrics.ts</span></span></code></pre></div></div>
<p>Here is a condensed view of <code>src/internal/monitoring/otel-metrics.ts</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode ts code-with-copy"><code class="sourceCode typescript"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> { HostMetrics } <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'@opentelemetry/host-metrics'</span></span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Initialize host metrics for Node.js runtime metrics</span></span>
<span id="cb7-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> hostMetrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">HostMetrics</span>({</span>
<span id="cb7-5">  meterProvider<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb7-6">  name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'storage-api-host-metrics'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb7-7">})</span>
<span id="cb7-8">hostMetrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">start</span>()</span></code></pre></div></div>
<p>We found it! This is what the full call path ends up looking like:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">src/internal/monitoring/otel-metrics.ts:235</span></span>
<span id="cb8-2">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> hostMetrics.start<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb8-3">       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> @opentelemetry/host-metrics → _createMetrics<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb8-4">          <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> registers a batchObservableCallback</span>
<span id="cb8-5">             <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> getNetworkData<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span>               <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[si.js:25]</span></span>
<span id="cb8-6">                <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> networkStats<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span>              <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[systeminformation/lib/network.js]</span></span>
<span id="cb8-7">                   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> getDefaultNetworkInterface<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb8-8">                      <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─</span> execSync → spawnSync → spawn</span></code></pre></div></div>
<p>The <a href="https://github.com/supabase/storage/pull/891">fix</a> we did for now was a simple one liner to emit the network metrics group:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode diff code-with-copy"><code class="sourceCode diff"><span id="cb9-1">const hostMetrics = new HostMetrics({</span>
<span id="cb9-2">  meterProvider,</span>
<span id="cb9-3">  name: 'storage-api-host-metrics',</span>
<span id="cb9-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">+ metricGroups: ['system.cpu', 'system.memory', 'process.cpu', 'process.memory'],</span></span>
<span id="cb9-5">})</span></code></pre></div></div>
<div class="callout callout-style-default callout-note callout-titled" title="">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>A long term fix is changing the <code>systeminformation</code> module itself to see if it can be made async.</p>
<p>There is an open PR titled: <a href="https://github.com/sebhildebrandt/systeminformation/pull/948">Use asynchronous operations everywhere to avoid blocking the main thread</a></p>
<p>but it was opened in 2024-11-22 with the last activity on 2025-03-05 so it doesn’t look like this will get merged anytime soon.</p>
</div>
</div>
</div>
<p>Here is a new flamegraph with the change:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/node-flamegraph-03.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:100.0%"></p>
</figure>
</div>
<p>Now for my favorite part, the event loop p99 latency across each of our app instances after we rolled out the fix:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/event-loop-delay.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:100.0%"></p>
</figure>
</div>
<p>Event loop latency measures how long a callback has to wait before the event loop picks it up. When the event loop is blocked by synchronous work, that wait time grows, meaning every request queued behind it is delayed.</p>
<p>We saw consistent spikes to ~1s and you can infer when the deployment took place based on the nosedive in the charts.</p>
<p>So a reminder, don’t block the event loop.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-unblocking-the-event-loop/</guid>
  <pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>A Subtle SQLite Mistake</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/subtle-sqlite-mistake/</link>
  <description><![CDATA[ 




<p>I noticed the SQLite query below had an average duration of ~90ms.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb1-2">    package_name, </span>
<span id="cb1-3">    package_summary</span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb1-5">    pypi_packages</span>
<span id="cb1-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> </span>
<span id="cb1-7">    package_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">like</span> ?</span>
<span id="cb1-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">order</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">by</span> </span>
<span id="cb1-9">    package_name</span>
<span id="cb1-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">limit</span> </span>
<span id="cb1-11">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/sentry-query-duration.png" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p><code>package_name</code> is the primary key and has an index on it. The table has 864,900 rows and is 166MB in size.</p>
<p>90ms for a query with a filter on the index, limited to 10 rows, on a table that is only 166 MB in size!? I would have expected something in the single digit millisecond range.</p>
<p>This query powers the active search results in <a href="https://pypacktrends.com">pypacktrends</a>, so as you type, package names start to appear. It takes the current value of the search input and appends <code>%</code> to match package names that start with the current prefix.</p>
<p>I ran a quick <code>explain query plan</code> to see what’s going on:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb2-1">.timer <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">on</span></span>
<span id="cb2-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">explain</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">query</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">plan</span> </span>
<span id="cb2-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb2-4">    package_name, </span>
<span id="cb2-5">    package_summary</span>
<span id="cb2-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb2-7">    pypi_packages</span>
<span id="cb2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> </span>
<span id="cb2-9">    package_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">like</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duck%'</span></span>
<span id="cb2-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">order</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">by</span> </span>
<span id="cb2-11">    package_name</span>
<span id="cb2-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">limit</span> </span>
<span id="cb2-13">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb2-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- QUERY PLAN</span></span>
<span id="cb2-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- SCAN pypi_packages USING INDEX sqlite_autoindex_pypi_packages_1</span></span>
<span id="cb2-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- Run Time: real 0.057 user 0.012548 sys 0.005846</span></span></code></pre></div></div>
<p>Huh, 57ms and it’s using a full index scan. After some <a href="https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators">research</a>, it turns out <code>like</code> is not case sensitive by default. Indexes, however, use binary collation by default. Collation is just the set of rules SQLite uses to compare and sort text (for example, whether A equals a, and how strings are ordered).</p>
<p>Because the search is case insensitive but the index uses binary collation, SQLite isn’t able to use the index efficiently. The simple fix is to make <code>like</code> case sensitive:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb3-1">.timer <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">on</span></span>
<span id="cb3-2">PRAGMA case_sensitive_like <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">ON</span>;</span>
<span id="cb3-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">explain</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">query</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">plan</span> </span>
<span id="cb3-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb3-5">    package_name, </span>
<span id="cb3-6">    package_summary</span>
<span id="cb3-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb3-8">    pypi_packages</span>
<span id="cb3-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> </span>
<span id="cb3-10">    package_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">like</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duck%'</span></span>
<span id="cb3-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">order</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">by</span> </span>
<span id="cb3-12">    package_name</span>
<span id="cb3-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">limit</span> </span>
<span id="cb3-14">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb3-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- QUERY PLAN</span></span>
<span id="cb3-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- SEARCH pypi_packages USING INDEX sqlite_autoindex_pypi_packages_1 (package_name&gt;? AND package_name&lt;?)</span></span>
<span id="cb3-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-- Run Time: real 0.004 user 0.000486 sys 0.001236</span></span></code></pre></div></div>
<p>4ms and <code>(package_name&gt;? AND package_name&lt;?)</code> shows we are now doing a range scan on the index. Much better.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/subtle-sqlite-mistake/</guid>
  <pubDate>Tue, 03 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries Setting Up A Proxy DHCP Server</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-setting-up-a-proxy-dhcp-server/</link>
  <description><![CDATA[ 




<p>I’m setting up my homelab and one of my goals is <a href="https://en.wikipedia.org/wiki/Zero-touch_provisioning">zero-touch provisioning</a>, plug in a machine and have it install itself over the network.</p>
<p>One common way to do that is <a href="https://en.wikipedia.org/wiki/Preboot_Execution_Environment">PXE booting</a>. Instead of booting from a USB stick, a client asks the network where to boot from.</p>
<p>PXE booting usually involves two protocols:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">Dynamic Host Configuration Protocol (DHCP)</a> for network settings and boot metadata</li>
<li><a href="https://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol">Trivial File Transfer Protocol (TFTP)</a> for downloading early boot files</li>
</ul>
<p>At home, my TP-Link Deco router (<code>192.168.68.1</code>) is the main DHCP server. It hands out IP addresses, gateway, DNS, and lease info. The issue is my Deco does not expose DHCP options for PXE boot settings.</p>
<p>So I used <a href="https://en.wikipedia.org/wiki/Dnsmasq">dnsmasq</a> on another host (<code>192.168.68.57</code>) as a Proxy DHCP server. In this setup dnsmasq only supplies PXE boot details (boot file + next server) while my router supplies the rest.</p>
<section id="capture-normal-dhcp" class="level2">
<h2 class="anchored" data-anchor-id="capture-normal-dhcp">Capture normal DHCP</h2>
<p>I started by looking at a normal DHCP exchange in <a href="https://www.wireshark.org/">Wireshark</a>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><video src="../../assets/videos/wireshark-dhcp-demo.mp4" class="img-fluid quarto-figure quarto-figure-center" controls=""><a href="../../assets/videos/wireshark-dhcp-demo.mp4">Video</a></video></p>
</figure>
</div>
<p>I selected <code>Wi-Fi: en0</code>, applied a <code>dhcp</code> filter, then forced a lease renew from my Mac:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> ipconfig set en0 dhcp</span></code></pre></div></div>
<p>That produced the standard DHCP flow:</p>
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">sequenceDiagram
  participant Client
  participant DHCP_Server as DHCP Server (192.168.68.1)
  Client-&gt;&gt;DHCP_Server: Discover (0.0.0.0 -&gt; 255.255.255.255)
  DHCP_Server--&gt;&gt;Client: Offer (IP lease proposal)
  Client-&gt;&gt;DHCP_Server: Request (accept offer)
  DHCP_Server--&gt;&gt;Client: ACK (lease confirmed)
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
<p>Quick notes that helped me:</p>
<ul>
<li><code>0.0.0.0</code> as source means the client does not have an IP yet</li>
<li><code>255.255.255.255</code> is limited broadcast (inside the local broadcast domain)</li>
</ul>
<p>Here are screenshots of the normal DHCP Offer:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/dhcp-offer.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:85.0%"></p>
</figure>
</div>
</section>
<section id="capture-proxy-dhcp" class="level2">
<h2 class="anchored" data-anchor-id="capture-proxy-dhcp">Capture Proxy DHCP</h2>
<p>My dnsmasq host (<code>buck</code>) runs on <code>192.168.68.57</code> and only proxies PXE info.</p>
<p>I won’t go into the details of setting up dnsmasq for proxy DHCP, since I simply followed this video and recommend you do the same: <a href="https://youtu.be/ew_JhL6PTrM?si=iG74dJcc4X2u_0Xl">PXE with Proxy DHCP</a></p>
<p>I captured the PXE attempt but running the following in on my dnsmasq host.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> tcpdump <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> eno1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-w</span> /tmp/proxydhcp-demo.pcap <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'(port 67 or port 68 or port 69 or port 4011)'</span></span></code></pre></div></div>
<p>When I opened the capture in Wireshark, you can see the PXE details in the DHCP offer:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/dhcp-proxy-offer.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:90.0%"></p>
</figure>
</div>
</section>
<section id="proxmox-caveat" class="level2">
<h2 class="anchored" data-anchor-id="proxmox-caveat">Proxmox Caveat</h2>
<p>For testing I was using a Proxmox VM but the Proxmox VM firmware identified itself as <a href="https://ipxe.org/">iPXE</a>. I could see valid Proxy DHCP offers from dnsmasq, but the VM did not always auto-follow them to TFTP.</p>
<p>To keep moving, I manually chained from the iPXE prompt:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource ipxe number-lines code-with-copy"><code class="sourceCode"><span id="cb3-1">dhcp</span>
<span id="cb3-2">chain tftp://192.168.68.57/boot.ipxe</span></code></pre></div></div>
<p>That successfully fetched <code>pxelinux.0</code> and proved the server-side setup was working.</p>
<p>Funny enough, for my mini PCs I plan on doing the exact opposite, since they only support standard PXE. I’ll be using PXE to load iPXE first, and then letting iPXE handle the rest of the boot chain.</p>


</section>

 ]]></description>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-setting-up-a-proxy-dhcp-server/</guid>
  <pubDate>Sun, 22 Feb 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Using AI to Contribute to Open Source</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/using-ai-to-contribute-to-os/</link>
  <description><![CDATA[ 




<p>I used AI to add a feature to <a href="https://mise.jdx.dev/">mise</a>, an open source tool (written in Rust) that manages installations of other tools.</p>
<p>I’m still coming to terms with this experience. I have never programed in Rust and I would be lying if I said I fully understood the code that it generated. I just wrote a <a href="../../blog/link-blog-the-future-of-software-engineering-is-sre">post</a> where I called out how many notable projects such as <a href="https://x.com/mitchellh/status/2014433315261124760">Ghostty</a>, <a href="https://nodejs.org/en/blog/announcements/hackerone-signal-requirement">Node.js</a>, <a href="https://github.com/curl/curl/pull/20312">curl</a>, <a href="https://github.com/tldraw/tldraw/issues/7695">tldraw</a> have limited or shut down external contributions after being overwhelmed with AI slop PRs.</p>
<p></p><div id="tweet-30305"></div><script>tweet={"url":"https:\/\/twitter.com\/mitchellh\/status\/2018458123632283679","author_name":"Mitchell Hashimoto","author_url":"https:\/\/twitter.com\/mitchellh","html":"\u003Cblockquote class=\"twitter-tweet\" align=\"center\"\u003E\u003Cp lang=\"en\" dir=\"ltr\"\u003EI&#39;ve been doing open source since I was a teenager (over 20yrs). And for the first time ever, I&#39;m considering closing external PRs to my OSS projects completely. This will throw the baby out with the bathwater and I hate that, but we close auto-opened slop PRs every single day.\u003C\/p\u003E&mdash; Mitchell Hashimoto (@mitchellh) \u003Ca href=\"https:\/\/twitter.com\/mitchellh\/status\/2018458123632283679?ref_src=twsrc%5Etfw\"\u003EFebruary 2, 2026\u003C\/a\u003E\u003C\/blockquote\u003E\n\u003Cscript async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"\u003E\u003C\/script\u003E\n\n","width":550,"height":null,"type":"rich","cache_age":"3153600000","provider_name":"Twitter","provider_url":"https:\/\/twitter.com","version":"1.0"};document.getElementById("tweet-30305").innerHTML = tweet["html"];</script><p></p>
<p>I did not want to be one of those people. At the end of the day it’s my name being attached to the PR and I take full responsibility for the code.</p>
<p>On the flip side, I have seen how AI can help. The same project, Ghostty, shows the benefits of AI and how it enables users who don’t know anything about the underlying technology contribute high quality issue reports.</p>
<p></p><div id="tweet-58972"></div><script>tweet={"url":"https:\/\/twitter.com\/mitchellh\/status\/2006114026191769924","author_name":"Mitchell Hashimoto","author_url":"https:\/\/twitter.com\/mitchellh","html":"\u003Cblockquote class=\"twitter-tweet\" align=\"center\"\u003E\u003Cp lang=\"en\" dir=\"ltr\"\u003ESlop drives me crazy and it feels like 95+% of bug reports, but man, AI code analysis is getting really good. There are users out there reporting bugs that don&#39;t know ANYTHING about our stack, but are great AI drivers and producing some high quality issue reports. \u003Cbr\u003E\u003Cbr\u003EThis person…\u003C\/p\u003E&mdash; Mitchell Hashimoto (@mitchellh) \u003Ca href=\"https:\/\/twitter.com\/mitchellh\/status\/2006114026191769924?ref_src=twsrc%5Etfw\"\u003EDecember 30, 2025\u003C\/a\u003E\u003C\/blockquote\u003E\n\u003Cscript async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"\u003E\u003C\/script\u003E\n\n","width":550,"height":null,"type":"rich","cache_age":"3153600000","provider_name":"Twitter","provider_url":"https:\/\/twitter.com","version":"1.0"};document.getElementById("tweet-58972").innerHTML = tweet["html"];</script><p></p>
<p>A very similar Ghostty example (though a different person) was actually discussed by David Crespo on the Oxide and Friends podcast: <a href="https://oxide-and-friends.transistor.fm/episodes/engineering-rigor-in-the-llm-age/transcript#t=32m13s">Engineering Rigor in the LLM Age</a>.</p>
<p>I resonated with many of the things David said:</p>
<blockquote class="blockquote">
<p>And I so that was what really unsettled me was that this was an area where I really knew nothing and just using my sort of, like, sense of what sounds like it makes sense to validate that I wasn’t gonna be posting AI slop on the ghosty GitHub, I was able to come to, you know, three real, bug reports without really putting myself putting very much into the process.</p>
</blockquote>
<blockquote class="blockquote">
<p>I didn’t know enough about how Ghostty worked or how Zig worked to Yeah. To really evaluate. So I was nervous, but I was, you know, upfront with a lot of humility of, like, I’m really not sure about this, but I but it sounds so good that I cannot hold it back.</p>
</blockquote>
<p>How can I be more like these contributors and use AI to produce high quality work?</p>
<p>I think it really boils down transparency. Be transparent with your use of AI, what you don’t know and show that you put some honest effort in. You can’t just generate AI slop and toss it over.</p>
<p>Here’s what my experience looked like going from question to merged PR.</p>
<p>In mise, you can run the <code>mise list</code> to show all tools mise “knows about”, buy many of the tools don’t display their source files unless you’re in the directory where that source config is located. For example:</p>
<pre><code>Tool        Version           Source                      Requested 
aws-vault   7.2.0            
bun         1.3.0             ~/.config/mise/config.toml  latest
kubectl     1.34.0           </code></pre>
<p>but I want to do something like <code>mise list --all-sources</code></p>
<pre><code>Tool        Version           Source                                Requested 
aws-vault   7.2.0             ~/code/work/infrastructure/mise.toml  latest
bun         1.3.0             ~/.config/mise/config.toml            latest
                              ~/code/work/infrastructure/mise.toml 
kubectl     1.34.0            ~/code/work/infrastructure/mise.toml  1.34.0</code></pre>
<p>This would allow me to see all sources for each tool across all my config files. I wanted this so I can see if there are some projects I can get rid of to clean up the amount of tools I have installed.</p>
<p>Mise has great docs on their <a href="https://mise.jdx.dev/contributing.html">contributing guidelines</a>. Before submitting a PR, they ask contributors to first open a discussion or mention the idea in their Discord.</p>
<p>I read all the docs on Mise and scanned the existing discussions to see if mise already allowed this. I couldn’t find anything so I opened a <a href="https://github.com/jdx/mise/discussions/7810">discussion</a> asking if this was something currently possible, if not, if they would be open to adding this feature.</p>
<p>I <a href="https://github.com/jdx/mise/discussions/7810#discussioncomment-15700363">followed up</a> with a screenshare of my fork of mise that added the feature to demo what I was looking for. The code was entirely AI generated and I wasn’t too concerned with the correctness at this point as I simply wanted to demo the feature.</p>
<p>I used opencode with GPT-5.2 Codex, you can see all my prompts <a href="https://opncd.ai/share/TViPRIxP">here</a>. I was very transparent with my use of AI when sharing the screenshare and even linked my session in the discussion.</p>
<p>I got a reply back from the maintainer “seems fine to me” which felt like a green light to open a PR.</p>
<p>This part was tough for me though because as I said I don’t know Rust, I have zero confidence if the code is “right” and was torn about opening a PR. Having code out there with my name on it that I don’t fully understand is unsettling.</p>
<p>I scoured the contributing guidelines over and over to make sure my change was properly tested, documentation was updated, the PR title was correct and so on. I ran the tests several times to make sure they were passing. I had several different AI agents review the code locally to make sure everything look good.</p>
<p>I opened the PR and noticed a few tests were failing and got some AI code review that I quickly addressed with a follow up commit. All CI was now passing. Now, all I had to do was wait.</p>
<p>To my surprise I woke up the next morning to <a href="https://github.com/jdx/mise/pull/8027">this</a>:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/mise-release-screenshot.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:75.0%"></p>
</figure>
</div>
<p>The PR was merged and has been added to the next release of mise.</p>
<p>My first reaction was, is this fair? Why should I be added as a contributor when AI did all the work? I was simply the “idea guy”. Is this how the future of software development is going to be?</p>
<p>It’s still unsettling to know there is code out there with my name attached to it that I don’t fully understand. The maintainer’s approval gives me some assurance that this code isn’t entirely AI slop as I assumed it wouldn’t have been merged otherwise.</p>
<p>I wanted to share this experience in hopes to promote more high quality AI generated PRs to open source repos. Remember it’s your name being attached to those PRs, your reputation on the line. Do you want to be known as the person who slings AI slop all over? “But Claude wrote it…” “ChatGPT told me…” is not an excuse. Take some responsibility.</p>
<div class="callout callout-style-default callout-warning callout-titled" title="AI use in writing">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>AI use in writing
</div>
</div>
<div class="callout-body-container callout-body">
<p>I used AI to help with some parts of this blog post. Below are my exact prompts and you can view the chat session <a href="https://chatgpt.com/share/6986013c-3df4-8004-ad9d-a058006c8054">here</a></p>
<blockquote class="blockquote">
<p>how can I add a transition here to go from talking about AI being used in open source contributions to actualy diving into the feature I waslooking for in mise:</p>
<p>How can I be more like David here and use AI for good? I think it really boils down transparency. Be transparent that you’re outside of your expertise and show that you put some honest effort into this work.</p>
<p>You can’t just generate AI slop and toss it over.</p>
<p>In mise, you can run the <code>mise list</code> to show all tools mise “knows about”, buy many of the tools don’t display their source files unless I’m in the directory where that source config is located. For example:</p>
</blockquote>
<blockquote class="blockquote">
<p>the wording is off here, can you help with the flow? The first thing they call out is, before submitting a PR they want you to create a discussion or mention it in their Discord.</p>
</blockquote>
</div>
</div>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/using-ai-to-contribute-to-os/</guid>
  <pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Running Software Outside of The Data Center</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/running-software-outside-of-the-dc/</link>
  <description><![CDATA[ 




<p>This weekend’s rabbit hole was a wild one. Lately, I’ve been poking around the mini PC market: the Lenovo Tiny series, HP Minis, and Dell Micros. You can usually find these on Facebook Marketplace or eBay for cheap. I recently picked up three HP ProDesk 600 G1 Minis for $100 total. Each one came with an Intel i5-4590T, 8GB of DDR3 RAM, and a 250GB SSD.</p>
<p>The specs are dated, but they’re still perfect for hands-on learning with Linux, Docker, and Kubernetes. They’re also very serviceable. It often takes just one screw to open the enclosure and get to the hardware.</p>
<p>I first came across these mini PCs through <a href="https://mini-rack.jeffgeerling.com/">Project MINI Rack</a> by Jeff Geerling. Instead of the traditional 19” server racks you see in data centers, there’s been a push toward 10” racks that are great for homelabs and portable network setups. These mini PCs are a great fit for that form factor, especially if you have access to a 3D printer and can print your own shelves.</p>
<p>Here’s what mine looks like:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/mini-rack.jpg" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:50.0%"></p>
</figure>
</div>
<p>It’s not just me getting interested in these. There’s been a growing movement in the tech community around self-hosting and moving away from cloud providers because of cost. Mini PCs are a great way to learn those skills.</p>
<p>One recent example I saw was how <a href="https://x.com/dhh/status/2016599019997290815">DHH was able to run Rails World campfire chat on a Beelink EQR5 out of his closet</a>. I’m not here to say “Cloud is bad, owning your own hardware is better”. Like most things, it depends on what you’re building.</p>
<p>For me this whole homelab, Linux, self-hosting journey is primarily educational. It’s hard to really understand the value cloud providers add through all their services and abstractions on top of a basic VPS if you’ve never done it the hard way yourself.</p>
<p>While digging into mini PC content, I came across this video: <a href="https://www.youtube.com/watch?v=bx4_QCX_khU">TinyMiniMicro Home Lab Revolution Introduction</a>. It mentioned how <a href="https://medium.com/chick-fil-atech/enterprise-restaurant-compute-f5e2fd63d20f">Chick-fil-A uses Intel NUC devices in their restaurants to host Kubernetes</a>. That led me to a KubeCon talk, <a href="https://www.youtube.com/watch?v=p5Vca4BoiJw">Renovating Edge Infrastructure at The Home Depot</a>, which describes a very similar architecture.</p>
<p>I know the term “edge” can come with some baggage, which is why I intentionally didn’t use it in the blog title. To me, “edge” just means compute that doesn’t live in a traditional data center.</p>
<p>A couple similarities that stood out to me between Chick-fil-A and Home Depot:</p>
<ul>
<li><strong>Eventual consistency</strong>: In store devices can’t constantly call back to the cloud, where the durable source of truth lives, because of latency and unreliable networks. Instead, they work off a local dataset that syncs periodically.</li>
<li><strong>The iPhone storage model</strong>: Applications on these devices treat local storage as temporary. Backups happen periodically, so data loss between syncs is possible. What matters is that the device can restart, reprovision, and get back to a working state quickly because the apps aren’t relying on local state.</li>
</ul>
<p>What really intrigues me about this style of infrastructure is that both the hardware and software are accessible enough that I can build something very similar in my own homelab.</p>
<p>Now that I have my mini rack put together, I’ve been looking for projects that lean toward Platform, Infrastructure, and Site Reliability work. That’s the direction I want to take my career, and building my own edge infrastructure platform at home feels like a good way to learn. More blog posts to come on this.</p>
<p>One thing I’ve been thinking about after going down this rabbit hole was this <a href="https://edgemonsters.dev/blog/edge-is-not-the-cloud/">blog post</a> title I came across:</p>
<blockquote class="blockquote">
<p>The Edge is not the cloud: Stop pretending they are the same thing.</p>
</blockquote>
<p>And a point called out in the Home Depot talk:</p>
<blockquote class="blockquote">
<p>“There are tons of storage solutions for Kubernetes. I almost need a sandbox up here on top of the stage. There are tons of storage solutions for Kube, but they’re all designed for not edge.”</p>
<p>To prove the difficulty of the problem, TenBrink recounted conversations with vendors from KubeCon: “Oh, what cloud are you running in?” TenBrink’s response: “I’m not. I’m running on my own boxes. We’re not for you.”</p>
</blockquote>
<p>It got me wondering: why can’t the edge be the cloud?</p>
<p>What if someone took the same philosophy Oxide did with their rack scale computer that provides API driven elastic infrastructure that you own and packaged it into a device that could be dropped into a local Chick-fil-A?</p>
<p>Something to think about.</p>
<p>If you are looking to learn more I recommend checking out the following resources:</p>
<ul>
<li><a href="https://edgemonsters.dev/blogs/">Edge Monsters Blog</a></li>
<li><a href="https://brianchambers.substack.com/">brianchambers.substack.com</a></li>
<li><a href="https://medium.com/chick-fil-atech">chick-fil-atech blog</a></li>
</ul>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/running-software-outside-of-the-dc/</guid>
  <pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>The future of software engineering is SRE</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/link-blog-the-future-of-software-eng-is-sre/</link>
  <description><![CDATA[ 




<p><a href="https://swizec.com/blog/the-future-of-software-engineering-is-sre/">The future of software engineering is SRE</a></p>
<p>This post made the rounds recently, landing on the front page of <a href="https://news.ycombinator.com/item?id=46759063">Hacker News</a> and all over my Twitter “For You” feed. It articulated some of the same feelings I’ve been having lately but haven’t been able to put into words.</p>
<blockquote class="blockquote">
<p><em>When code gets cheap operational excellence wins.</em></p>
</blockquote>
<p>This line stuck with me.</p>
<p>The genie is out of the bottle. People are going to be writing code at an unprecedented scale with AI agents and we’re already seeing the downsides. Several notable open source projects such as <a href="https://x.com/mitchellh/status/2014433315261124760">Ghostty</a>, <a href="https://nodejs.org/en/blog/announcements/hackerone-signal-requirement">Node.js</a>, <a href="https://github.com/curl/curl/pull/20312">curl</a>, <a href="https://github.com/tldraw/tldraw/issues/7695">tldraw</a> have limited or shut down external contributions after being inundated with AI generated PRs.</p>
<p>This begs the question, how do we gain confidence this AI generated code “works”?</p>
<p>To me, this is fundamentally ops work. The real problem is “confidence” is subjective. It’s not about 100% test coverage, it’s the feeling when I ship this, everything is going to be okay.</p>
<p>If a company has a reliable CI/CD pipeline, strong observability, and safe rollback procedures, it almost doesn’t matter where the code came from. Human. AI. Intern. Vendor. What matters is whether the product can safely absorb change.</p>
<p>So lets <a href="https://charity.wtf/2026/01/19/bring-back-ops-pride-xpost/">bring back ops pride</a> and get ready for software engineering in this new era.</p>



 ]]></description>
  <category>link blog</category>
  <guid>https://www.tylerhillery.com/blog/link-blog-the-future-of-software-eng-is-sre/</guid>
  <pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries Building a Chrome Extension</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-building-a-chrome-ext/</link>
  <description><![CDATA[ 




<hr>
<p>There is nothing more embarrassing sharing a link with someone with a bunch of utm query parameters <a href="https://www.tylerhillery.com/?utm_source=share&amp;utm_content=share_button">https://www.tylerhillery.com/?utm_source=share&amp;utm_content=share_button</a>. Which is why I built <a href="https://chromewebstore.google.com/detail/url-clipr/jhfogpjaehahecdimpnfnohpjmamicci">URL Clipr</a>, a chrome extension that removes unwanted query parameters.</p>
<p>Users can define a list of patterns (currently limited to “starts with” patterns) that will be excluded when copying the URL. There are three ways to copy the URL:</p>
<ol type="1">
<li><strong>Shortcut</strong> CTRL+Shift+U / Command+Shift+U which can be modified at <a href="chrome://extensions/shortcuts">chrome://extensions/shortcuts</a></li>
<li><strong>Copy Button</strong> in the top right corner of the popup</li>
<li><strong>Context Menu</strong> when right clicking a link on a web page.</li>
</ol>
<p>I could add a pattern such as <code>utm</code> and when I copy the URL it would go from <a href="">https://www.tylerhillery.com/?utm_source=share&amp;utm_content=share_button</a> to <a href="">https://www.tylerhillery.com</a></p>
<p>I never built a chrome extension before so the first thing I did was created a playground repo to see how chrome extensions work. Starting a playground repo is one of the first things I do when learning anything new. It provides a no stress way to experiment. I can often get caught up in the ancillary tasks of a project like CI/CD, code formatting, repo structure, testing etc. Playgrounds allow me to ignore all of that and focus solely on the thing I am learning.</p>
<p>The <a href="https://developer.chrome.com/docs/extensions/get-started">get started</a> docs for chrome extension development is where I began. Once I finished this guide I started some searching to see if anyone had a preexisting template I could use with built in CI/CD to help with publishing the extension. Eventually I came across this framework called <a href="https://wxt.dev/">WXT</a> which has the tagline:</p>
<blockquote class="blockquote">
<p>an open source tool that makes web extension development faster than ever before.</p>
</blockquote>
<p>At first it seemed a little overkill for the extension I was trying to build but I liked the idea that I could eventually publish this extension to multiple browsers. WXT does allow a pretty bare bones setup so you can ignore using a frontend framework like React, Vue, Svelte. I was actually surprised to learn that chrome extension popups are just plain HTML/CSS/JS. Not sure why I was expecting anything different.</p>
<p>WXT has a good guide, and my biggest takeaway was learning how a Chrome extension can have multiple entry points. These entry points define how the extension starts and where its functionality lives. For URL Clipr, the two I needed were the background and popup entry points.</p>
<p>The background entrypoint is responsible for adding the copy button in the context menu on right clicks. This is done by using <code>browser.contextMenus.create</code>. Then you can add an <code>onClicked</code> listener to apply the cleaning logic and add to clipboard. The other listener the background entrypoint sets up is for the <code>copy-url</code> event which is created as a shortcut in the <code>wxt.config.ts</code> file:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource typescript number-lines code-with-copy"><code class="sourceCode typescript"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">export</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">default</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">defineConfig</span>({</span>
<span id="cb1-2">  srcDir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"src"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-3">  imports<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-4">  manifest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-5">    name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"URL Clipr"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-6">    permissions<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"storage"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"activeTab"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contextMenus"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scripting"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-7">    commands<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-8">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"copy-url"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-9">        suggested_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> {</span>
<span id="cb1-10">          <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">default</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ctrl+Shift+U"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-11">          mac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Command+Shift+U"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-12">        }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-13">        description<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Copy URLs without unwanted query params"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-14">      }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-15">    }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-16">  }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-17">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>The only difference from the context menu on click event is the <code>copy-url</code> event has to use <code>browser.tabs.query</code> to get the active URL.</p>
<p>The popup entry point shows the UI when you click on the extension. It’s where the user can specify the list of patterns to exclude. In full transparency the main UI code for the popup was AI generated. I wouldn’t say “vide coded” as I did thoroughly review the code, even though HTML/CSS is not my strong suite.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.tylerhillery.com/assets/images/url-clipr-popup.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:50.0%"></p>
</figure>
</div>
<p>The patterns are stored in local storage and retrieved whenever a URL needs to be cleaned. What surprised me was how much trickier the cleaning logic turned out to be than I expected. I initially planned to use a flexible regex-based approach that could handle cases like “starts with” “ends with,” “contains,” and “equals.” My idea was to build something like <code>[?&amp;])(?:${sources.join('|')})=[^&amp;]*(?=&amp;|$)</code>, where sources would come from the saved patterns, along with a dropdown that lets the user specify the pattern type. That way, the patterns could be stored like this:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource typescript number-lines code-with-copy"><code class="sourceCode typescript"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> patterns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb2-2">  { startsWith<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'utm'</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-3">  { contains<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'__'</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-4">  { endsWith<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'with'</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-5">  { exact<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'foo*bar'</span> }</span>
<span id="cb2-6">]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>I have a confession to make though, I don’t understand regex that well and every time I use it I have to use <a href="https://regexr.com">regexr.com</a> or <a href="https://regex101.com/">https://regex101.com/</a> to breakdown the pattern for me. The pattern I came up with felt overly complex so I kept it simple for the first version and only allowed “starts with” patterns which allows me to use very basic JS string methods</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource typescript number-lines code-with-copy"><code class="sourceCode typescript"><span id="cb3-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>((param) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>patterns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">some</span>((pattern) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> param<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">startsWith</span>(pattern)))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Another aspect that wasn’t as straight forward as I anticipated was decoding and encoding URLs. The core function that cleans the URL takes in a string version of the URL with the list of patterns to filter out.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource typescript number-lines code-with-copy"><code class="sourceCode typescript"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">urlClipr</span>(urlStr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> patterns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span>[])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span></span></code></pre></div></div>
<p>I convert the <code>urlStr</code> to a <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL">URL</a> object. My original plan was to use the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams">URLSearchParams</a> object but I want to see if you can notice something in the below example:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">personal/url-clipr</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> </span>
<span id="cb5-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> node</span>
<span id="cb5-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Welcome</span> to Node.js v24.11.1.</span>
<span id="cb5-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Type</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".help"</span> for more information.</span>
<span id="cb5-5"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> const <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">url</span> = new URL<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://example.com?utm_source=email&amp;message=hello%20world#heading"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb5-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">undefined</span></span>
<span id="cb5-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> url.searchParams.toString<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">()</span></span>
<span id="cb5-8"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'utm_source=email&amp;message=hello+world'</span></span></code></pre></div></div>
<p>Did you spot it? The encoding is different for <code>searchParams</code>, you get <code>hello+world</code> vs <code>hello%20world</code>. This is actually mentioned in the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#interaction_with_url.searchparams">docs</a>:</p>
<blockquote class="blockquote">
<p>However, URL.search encodes a subset of characters that URLSearchParams does, and encodes spaces as %20 instead of +. This may cause some surprising interactions—if you update searchParams, even with the same values, the URL may be serialized differently.</p>
</blockquote>
<p>This made it tricky to use any built in objects so instead I operated on the raw string itself to “keep it simple stupid”.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource typescript number-lines code-with-copy"><code class="sourceCode typescript"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">export</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">urlClipr</span>(urlStr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> patterns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span>[])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span> {</span>
<span id="cb6-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">URL</span>(urlStr)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-3"></span>
<span id="cb6-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> raw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> url<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">search</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-5"></span>
<span id="cb6-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> raw</span>
<span id="cb6-7">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&amp;"</span>)</span>
<span id="cb6-8">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>((param) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> param <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb6-9">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>((param) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>patterns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">some</span>((pattern) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">=&gt;</span> param<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">startsWith</span>(pattern)))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-10"></span>
<span id="cb6-11">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">${</span>url<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">origin</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}${</span>url<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pathname</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}${</span></span>
<span id="cb6-12">    params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"?"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">join</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&amp;"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span></span>
<span id="cb6-13">  <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}${</span>url<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">hash</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-14">}</span></code></pre></div></div>
<div class="callout callout-style-default callout-note callout-titled" title="Side Note">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Side Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>It’s funny how this is the core logic for the entire extension. Everything else is mainly setting up listeners, dealing with storage, UI code etc.</p>
</div>
</div>
</div>
<p>If it wasn’t for setting up a comprehensive test suite I wouldn’t have caught this subtle difference! Speaking of testing, WXT has great built in tools for testing. WXT spins up a browser with the extension preinstalled in dev mode. I was very impressed by WXT as you can tell the creators thought deeply about entire DX from development to publishing.</p>
<p>The toughest part for me was figuring out how to publish the extension to the chrome web store. WXT makes this easy and has a guide on how to do so with <a href="https://wxt.dev/guide/essentials/publishing.html#github-action">GitHub Actions</a> but the part I got tripped up on was where to get the following environment variables:</p>
<pre><code>- name: Submit to stores
        run: |
          pnpm wxt submit \
            --chrome-zip .output/*-chrome.zip \
        env:
          CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
          CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
          CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
          CHROME_REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}</code></pre>
<p>To get the extension ID I had to upload the extension manually for the first time. The <code>CLIENT_ID</code>, <code>CLIENT_SECRET</code> and <code>REFRESH_TOKEN</code> were the tougher parts. That was until I found this <a href="https://developer.chrome.com/docs/webstore/using-api">guide</a> on publishing chrome extensions programmatically using the Chrome Web Store API. It walks you through everything step by step.</p>
<p>URL Clipr is <a href="https://chromewebstore.google.com/detail/url-clipr/jhfogpjaehahecdimpnfnohpjmamicci">live</a> now, so give it try. Right now it only supports “starts with” patterns which honestly covers everything for me (mainly <code>utm</code> and <code>__</code>) but if there is enough demand for other patterns I will look into adding them.</p>
<p>Now feel free to save and share those URLs without those unwanted query parameters!</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-building-a-chrome-ext/</guid>
  <pubDate>Tue, 20 Jan 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries DTrace</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-dtrace/</link>
  <description><![CDATA[ 




<hr>
<p>As I have been making my way through the <a href="https://nodejs.org/en/learn/getting-started/introduction-to-nodejs">learn</a> section on the <a href="https://nodejs.org/en">Node.js</a> website, I came across a pleasant surprise in the <a href="https://nodejs.org/en/learn/modules/backpressuring-in-streams">Backpressuring in Streams</a> section:</p>
<p><img src="https://www.tylerhillery.com/assets/images/node-backpressure-dtrace.png" class="img-fluid"></p>
<p>That’s right, <a href="https://illumos.org/books/dtrace/preface.html#preface"><code>dtrace</code></a> mentioned! Over the past ~5 months, I have gone through the entire <a href="https://oxide-and-friends.transistor.fm/">Oxide and Friends</a> podcast backlog, and it’s left a lasting impact on how I think about technology and software engineering. I shared more about my thoughts in this <a href="https://tylerhillery.com/blog/oxide-and-friends/">blog post</a>.</p>
<p>DTrace comes up frequently in the podcast since Bryan Cantrill, one of the co-hosts, was its creator and Adam Leventhal, the other co-host, was also one of its original developers. I’m familiar with the tool from those discussions, even though I haven’t used it myself.</p>
<p>When learning a new programming language, I personally like to type out the examples myself and run them. However, the backpressure example didn’t go through how to instrument it with DTrace to get the results they mentioned, so I used this as an opportunity to give DTrace a spin!</p>
<p>First, what is DTrace? DTrace is a dynamic tracing framework, and we’ll be using it here to measure GC (garbage collection) times in Node.js to see the effects of backpressure disabled.</p>
<p>As described in the docs, backpressure is the buildup of data behind a buffer during data transfer. <a href="https://nodejs.org/api/stream.html#stream_writable_streams"><code>Streams</code></a> in Node.js allow you to process data incrementally versus loading the entire dataset into memory. Backpressure in Node.js occurs when the <a href="https://nodejs.org/api/stream.html#stream_readable_streams"><code>Readable</code></a> stream produces too much data for the <a href="https://nodejs.org/api/stream.html#stream_writable_streams"><code>Writable</code></a> stream to handle.</p>
<p>When the <code>Writable</code> stream can’t keep up the data gets put into a queue waiting to be processed. This queue will continue to grow as long as the <code>Writable</code> stream stays behind. Managing this queue from building up is what Node’s backpressure mechanism does.</p>
<div class="callout callout-style-default callout-note callout-titled" title="Note">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>One thing that tripped me up is the term <em>“backpressure”</em> is often used in two ways:</p>
<ul>
<li>to describe the <strong>problem</strong>, when the consumer can’t keep up with the producer, leading to data buildup.</li>
<li>to describe the <strong>solution</strong>, the mechanism that regulates or slows down the producer to prevent overload.</li>
</ul>
</div>
</div>
</div>
<p>The example provided in the docs show compressing a video file because writing to disk is a lot slower than reading from disk. This provides a good way to demonstrate the effects of backpressure. If we turn off the backpressure mechanism, memory usage spikes and garbage collection runs more often, which is exactly what we’ll measure with DTrace.</p>
<p>Of course, before I could actually run the example, I ran into my first problem. The example uses a 9GB video file, <code>The.Matrix.1080p.mkv</code>. Unfortunately, I don’t just have a 9 GB video lying around. I asked ChatGPT where I could download a free large video file, which led me to something called “Big Buck Bunny.”</p>
<p>Ummm… what? I risked it and clicked the suspicious looking link which greeted me with this:</p>
<p><img src="https://www.tylerhillery.com/assets/images/big-buck-bunny-landing-page.png" class="img-fluid"></p>
<p>After some further research, it appears to be a legit free open movie from the <a href="https://www.blender.org/about/foundation/">Blender Foundation</a> licensed under the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 license</a>. The more you know!</p>
<p>Anywho, I downloaded what I thought would be the largest file available:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> curl <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-O</span> http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_native_60fps_stereo_abl.mp4</span>
<span id="cb1-2">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">%</span> Total    % Received % Xferd  Average Speed   Time    Time     Time  Current</span>
<span id="cb1-3">                                 <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Dload</span>  Upload   Total   Spent    Left  Speed</span>
<span id="cb1-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">100</span> 1020M  100 1020M    0     0  1190k      0  0:14:38  0:14:38 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--:--:--</span>  639k</span></code></pre></div></div>
<p>It’s only 1020MB, so I used ffmpeg to repeat it 8 more times to get 9GB as I wanted to have a similar file size as the example.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node-js-notes/intro-to-node-js</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span> </span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> ffmpeg <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-stream_loop</span> 8 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> bbb_sunflower_native_60fps_stereo_abl.mp4 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> copy bbb_repeat_9_times.mp4</span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node-js-notes/intro-to-node-js</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span> </span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> ls <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-lh</span> bbb_repeat_9_times.mp4</span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-rw-r--r--@</span> 1 tyler  staff   8.9G Oct 15 18:11 bbb_repeat_9_times.mp4</span></code></pre></div></div>
<p>8.9GB should do.</p>
<p>After looking into the example more, it looks like we need to compile a custom build of Node.js taking out the <a href="https://github.com/nodejs/node/blob/55c42bc6e5602e5a47fb774009cfe9289cb88e71/lib/_stream_writable.js#L239">return value</a> of the <code>.write()</code> function, which effectively disables backpressure support.</p>
<p>I decided to use the latest LTS version, which at the time of writing this is v22.20.0.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> clone <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--branch</span> v22.20.0 https://github.com/nodejs/node.git</span></code></pre></div></div>
<p>Doesn’t look like <code>node/lib/_stream_writable.js</code> contains that function anymore.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// https://github.com/nodejs/node/blob/v22.20.0/lib/_stream_writable.js</span></span>
<span id="cb4-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'use strict'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Keep this file as an alias for the full stream module.</span></span>
<span id="cb4-5"></span>
<span id="cb4-6">module<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">exports</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">require</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'stream'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Writable</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>The link they provided was a permalink to a <a href="https://github.com/nodejs/node/commit/55c42bc6e5602e5a47fb774009cfe9289cb88e71">commit</a> that took place 9 years ago.</p>
<p>Using go to definition, it takes me to <code>node/lib/stream.js</code> which contains another import from <code>/node/lib/internal/streams/writable.js</code>. Ah finally, the <code>Writable.prototype.write</code> function, but wait no <code>return ret</code> line:</p>
<p><img src="https://www.tylerhillery.com/assets/images/git-diff-writable-node-func.png" class="img-fluid"></p>
<div class="callout callout-style-default callout-note callout-titled" title="Side Note">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Side Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>I was looking for a way to display a nice git diff between the old and new <code>write</code> function which is how I stumbled across this wonderful tool called <a href="https://github.com/dandavison/delta">delta</a>.</p>
<p>I can’t believe I haven’t heard of this before! Now I can have beautiful git diffs right in my terminal.</p>
</div>
</div>
</div>
<p>After doing a couple more go to definitions, I found the little sucker defined in the <a href="https://github.com/nodejs/node/blob/caa20e28dc1f21a97f7b2a7134973fd6435b65f0/lib/internal/streams/writable.js#L548"><code>writeOrBuffer()</code></a> function in the <code>/node/lib/internal/streams/writable.js</code> file.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Return false if errored or destroyed in order to break</span></span>
<span id="cb5-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// any synchronous while(stream.write(data)) loops.</span></span>
<span id="cb5-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ret <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> (state[kState] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> (kDestroyed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> kErrored)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>I replaced this line with <code>return true</code> instead.</p>
<p>The next step is to build Node.js from source. Luckily, Node.js has some great <a href="https://github.com/nodejs/node/blob/v22.20.0/BUILDING.md">documentation</a> on how to do so. I am pretty sure I had all the required prerequisites to run the build process, so I went forward with the commands outlined in the guide:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CXX</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>g++-12</span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">./configure</span></span>
<span id="cb6-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j4</span></span></code></pre></div></div>
<p>Buttt it blew up on me when I ran <code>./configure</code></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">intro-to-node-js/node</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v22.20.0</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span> </span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> ./configure</span>
<span id="cb7-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Node.js</span> configure: Found Python 3.13.8...</span>
<span id="cb7-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Traceback</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">most</span> recent call last<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">:</span></span>
<span id="cb7-5">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/Users/tyler/code/learning/node-js-notes/intro-to-node-js/node/./configure"</span>, line 28, in <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>module<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb7-6">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">import</span> configure</span>
<span id="cb7-7">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/Users/tyler/code/learning/node-js-notes/intro-to-node-js/node/configure.py"</span>, line 2274, in <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>module<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb7-8">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">check_compiler</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">output</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb7-9">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">~~~~~~~~~~~~~~^^^^^^^^</span></span>
<span id="cb7-10">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/Users/tyler/code/learning/node-js-notes/intro-to-node-js/node/configure.py"</span>, line 1237, in check_compiler</span>
<span id="cb7-11">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ok,</span> is_clang, clang_version, gcc_version = try_check_compiler<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">CXX,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'c++'</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb7-12">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span></span>
<span id="cb7-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ValueError:</span> too many values to unpack <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">expected</span> 4<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span></code></pre></div></div>
<p>Hmmm, I set up a breakpoint on that line to step into what’s happening with <code>try_check_compiler(CXX, 'c++')</code>. There are only two <code>return</code> statements in there, and only one of them returns more than four values, which implies I was hitting an <code>OSError</code>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">OSError</span>:</span>
<span id="cb8-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
<p>Oddly enough I didn’t hit that error running it directly through the VS Code debugger. This is puzzling. I never used the built in <code>pdb</code> before but I thought I would give that a try and indeed it raised the <code>OSError</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1">➜ .<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure</span>
<span id="cb9-2">Node.js configure: Found Python <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3.13.9</span>...</span>
<span id="cb9-3"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1238</span>)check_compiler()</span>
<span id="cb9-4"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pdb<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> pdb.set_trace()</span>
<span id="cb9-5">(Pdb) n</span>
<span id="cb9-6"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1239</span>)check_compiler()</span>
<span id="cb9-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> ok, is_clang, clang_version, gcc_version <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> try_check_compiler(CXX, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'c++'</span>)</span>
<span id="cb9-8">(Pdb) s</span>
<span id="cb9-9"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span>Call<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span></span>
<span id="cb9-10"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1115</span>)try_check_compiler()</span>
<span id="cb9-11"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> try_check_compiler(cc, lang):</span>
<span id="cb9-12">(Pdb) n</span>
<span id="cb9-13"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1116</span>)try_check_compiler()</span>
<span id="cb9-14"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb9-15">(Pdb) n</span>
<span id="cb9-16"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1117</span>)try_check_compiler()</span>
<span id="cb9-17"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> proc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subprocess.Popen(shlex.split(cc) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-E'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-P'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-x'</span>, lang, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>],</span>
<span id="cb9-18">(Pdb) n</span>
<span id="cb9-19"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1118</span>)try_check_compiler()</span>
<span id="cb9-20"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> stdin<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>subprocess.PIPE, stdout<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>subprocess.PIPE)</span>
<span id="cb9-21">(Pdb) n</span>
<span id="cb9-22"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1117</span>)try_check_compiler()</span>
<span id="cb9-23"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> proc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subprocess.Popen(shlex.split(cc) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-E'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-P'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-x'</span>, lang, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>],</span>
<span id="cb9-24">(Pdb) n</span>
<span id="cb9-25"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">FileNotFoundError</span>: [Errno <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] No such <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> directory: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'g++-12'</span></span>
<span id="cb9-26"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1117</span>)try_check_compiler()</span>
<span id="cb9-27"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> proc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subprocess.Popen(shlex.split(cc) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-E'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-P'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-x'</span>, lang, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-'</span>],</span>
<span id="cb9-28">(Pdb) n</span>
<span id="cb9-29"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1119</span>)try_check_compiler()</span>
<span id="cb9-30"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">OSError</span>:</span>
<span id="cb9-31">(Pdb) n</span>
<span id="cb9-32"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>Users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>tyler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>learning<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>notes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>intro<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>js<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>node<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>configure.py(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1120</span>)try_check_compiler()</span>
<span id="cb9-33"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
<p>Ahhh I’m an idiot. <code>FileNotFoundError: [Errno 2] No such file or directory: 'g++-12'</code> I blindly just copied the command <code>export CXX=g++-12</code>, but I don’t have that installed. The VS Code debugger didn’t have <code>CXX</code> set because I just set that environment variable within my terminal session.</p>
<p>After unsetting <code>CXX</code> it completed successfully.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ntro-to-node-js/node</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v22.20.0</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span> </span>
<span id="cb10-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> ./configure</span>
<span id="cb10-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Node.js</span> configure: Found Python 3.13.9...</span>
<span id="cb10-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">INFO:</span> configure completed successfully</span></code></pre></div></div>
<p>The next step was running make:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j4</span></span></code></pre></div></div>
<p>A couple of minutes after running the command, I left hoping it would be finished when I got back. 10 minutes later I returned, and I thought my MacBook was getting ready for takeoff. Seriously, listen:</p>
<audio controls="">
  <source src="../../assets/audio/mac-fans.mp3" type="audio/mpeg">
  Your browser doesn't support the audio element.
</audio>
<p>This was the first time I have ever had my fans turn on for this machine. Eventually, the build did complete in about ~30min.</p>
<p>I copied the <a href="https://nodejs.org/en/learn/modules/backpressuring-in-streams#too-much-data-too-quickly"><code>stream/promises</code></a> example they had and ran the script for both versions, modified (backpressure disabled) and an unmodified version of Node.js:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource console number-lines code-with-copy"><code class="sourceCode"><span id="cb12-1">   trial (#)  | `node` binary (ms) | modified `node` binary (ms)</span>
<span id="cb12-2">=================================================================</span>
<span id="cb12-3">      1       |      137040        |          139900   </span>
<span id="cb12-4">      2       |      136362        |          139999   </span>
<span id="cb12-5">      3       |      141825        |          142009   </span>
<span id="cb12-6">      4       |      136131        |          143897   </span>
<span id="cb12-7">      5       |      139041        |          142208   </span>
<span id="cb12-8">=================================================================</span>
<span id="cb12-9">average time: |      138080        |          141603 </span></code></pre></div></div>
<p>Slower than the example, but I am going to chalk that up to “my machine vs their machine” and user error. The numbers between the unmodified and modified versions are comparable, which is what I wanted to see.</p>
<p>Now it’s time to setup DTrace to reproduce the GC measured time. I recall in a <a href="https://youtu.be/J10nd1UdSys?si=1ZRJArQekLYzoAbO&amp;t=2511">talk</a> by Adam Leventhal, DTrace was “castrated” when macOS released <a href="https://developer.apple.com/documentation/security/disabling-and-enabling-system-integrity-protection">System Integrity Protection (SIP)</a>. Disabling SIP made me feel uneasy. After some googling though, I came across this <a href="https://jade.fyi/blog/misadventures-in-dtrace/">blog post</a>, which used <a href="https://mac.getutm.app/">UTM</a> to create a macOS virtual machine with SIP disabled.</p>
<p>This was something I was much more comfortable with, so I spun up a VM in recovery mode and ran <code>csrutil disable</code> to disable SIP.</p>
<div class="callout callout-style-default callout-note callout-titled" title="Note">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Note
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>I later learned that disabling SIP wasn’t needed for what I was trying to measure. If I would have done a better job of listening to Adam in his talk, he clearly states:</p>
<blockquote class="blockquote">
<p>If you’re running the pid provider, if you’re looking at processes that you own, if you’re looking at USDT probes, all of that can be done with SIP enabled.</p>
</blockquote>
<p>Which is all I needed for the Node.js probes.</p>
</div>
</div>
</div>
<p>macOS comes with <code>dtrace</code> preinstalled, so with a little help from GitHub Copilot, I asked if it could show me how to measure Node.js GC time.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tylerhillery@Tylers-Virtual-Machine</span> intro-to-node-js % sudo dtrace <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'node*:::gc-start { self-&gt;ts = timestamp; }</span></span>
<span id="cb13-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                node*:::gc-done /self-&gt;ts/ { printf("%d ms\n", (timestamp - self-&gt;ts)/1000000); self-&gt;ts = 0; }'</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> 15088</span>
<span id="cb13-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dtrace:</span> invalid probe specifier node<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>:::gc-start { self-<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>ts = timestamp<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb13-4">                <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">node*:::gc-done</span> /self-<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>ts/ { printf<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"%d ms\n"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">,</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">timestamp</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-</span> self-<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>ts<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/1000000</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">);</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">self-</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>ts = 0<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">}</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> probe description node<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>:::gc-start does not match any probes</span></code></pre></div></div>
<p>Hmmm, doesn’t look like my Node.js process is generating any DTrace probes. After some more googling, it appears Node.js doesn’t enable DTrace probes by default, but apparently I can enable them with a flag. I couldn’t find any mentions of DTrace in the Node.js codebase, but after grepping through the commit history, I was able to find this <a href="https://github.com/nodejs/node/commit/aa3a572e6bee116cde69508dc29478b40f40551a">commit</a>:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">intro-to-node-js/node</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v22.20.0</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span> </span>
<span id="cb14-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git show <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-patch</span> aa3a572e6be</span>
<span id="cb14-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">commit</span> aa3a572e6bee116cde69508dc29478b40f40551a</span>
<span id="cb14-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Date:</span>   Sun Jul 17 18:33:52 2022 +0200</span>
<span id="cb14-5"></span>
<span id="cb14-6">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">build:</span> remove dtrace <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">etw</span> support</span>
<span id="cb14-7">    </span>
<span id="cb14-8">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">There</span> are no clear indicators anyone is using the dtrace USDT probes.</span>
<span id="cb14-9">    </span>
<span id="cb14-10">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ETW</span> support is very intertwined with the dtrace infrastructure. It<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'s not</span></span>
<span id="cb14-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    clear if anyone uses ETW so to keep things simple it too is removed.</span></span>
<span id="cb14-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    </span></span>
<span id="cb14-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    Fixes: https://github.com/nodejs/node/issues/43649</span></span>
<span id="cb14-14"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    </span></span>
<span id="cb14-15"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    PR-URL: https://github.com/nodejs/node/pull/43652</span></span></code></pre></div></div>
<p>You got to be kidding me. Well, it was at this moment that I found out Node.js <a href="https://nodejs.org/en/learn/diagnostics/memory/using-gc-traces">recommends</a> using the <code>--trace-gc</code> flag for measuring GC nowadays.</p>
<p>But I have come so far, and I really wanted to see if I could get DTrace working on the latest LTS release. I could use an older version of Node.js that had DTrace enabled, but that’s no fun. Do it for the <del>gram</del> blog!</p>
<p>The problem is my C++ skills are lacking… to say the least, and the codebase has changed so much since DTrace was removed that a simple <code>git revert</code> wouldn’t help here. This seemed like a good use case for AI though, as I can provide it the context of the diff where it was removed and see if it can add it back in.</p>
<p>I gave Copilot the task, and a few minutes later I had a successful build of Node.js v22.20.0 with DTrace enabled. No clue if it’s actually right, but I don’t really care at this point. I just wanted to see those Node.js probes!</p>
<p>You might be asking, what is a probe anyway? The <a href="https://illumos.org/books/dtrace/bookinfo.html#bookinfo">Dynamic Tracing Guide</a> has a nice section on them:</p>
<blockquote class="blockquote">
<p>DTrace helps you understand a software system by enabling you to dynamically modify the operating system kernel and user processes to record additional data that you specify at locations of interest, called probes. A probe is a location or activity to which DTrace can bind a request to perform a set of actions, like recording a stack trace, a timestamp, or the argument to a function. Probes are like programmable sensors scattered all over your illumos system in interesting places.</p>
</blockquote>
<p>With this helpful context, let’s see if we can see those probes now:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tylerhillery@Tylers-Virtual-Machine</span> node-js-notes % sudo dtrace <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'node*:::gc*'</span>     </span>
<span id="cb15-2">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ID</span>   PROVIDER            MODULE                          FUNCTION NAME</span>
<span id="cb15-3"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2904</span>   node2008              node _ZN4node14dtrace_gc_doneEPN2v87IsolateENS0_6GCTypeENS0_15GCCallbackFlagsEPv [node::dtrace_gc_done<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v8::Isolate*,</span> v8::GCType, v8::GCCallbackFlags, void<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">]</span> gc-done</span>
<span id="cb15-4"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2905</span>   node2008              node _ZN4node15dtrace_gc_startEPN2v87IsolateENS0_6GCTypeENS0_15GCCallbackFlagsEPv [node::dtrace_gc_start<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v8::Isolate*,</span> v8::GCType, v8::GCCallbackFlags, void<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">]</span> gc-start</span></code></pre></div></div>
<p>We are back in business baby.</p>
<p>Let’s try tracking GC times again and break down each step of this <code>dtrace</code> command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tylerhillery@Tylers-Virtual-Machine</span> node-js-notes % sudo dtrace <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dtrace:::BEGIN { start = timestamp; } node2008:::gc-start { self-&gt;ts = timestamp; } node2008:::gc-done /self-&gt;ts/ { printf("%d,%d\n", (timestamp - start)/1000000, (timestamp - self-&gt;ts)/1000000); self-&gt;ts = 0; }'</span></span>
<span id="cb16-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dtrace:</span> description <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dtrace:::BEGIN '</span> matched 3 probes</span>
<span id="cb16-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">CPU</span>     ID                    FUNCTION:NAME</span>
<span id="cb16-4">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2</span>   2904 _ZN4node14dtrace_gc_doneEPN2v87IsolateENS0_6GCTypeENS0_15GCCallbackFlagsEPv:gc-done 173,0</span>
<span id="cb16-5">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">0</span>   2904 _ZN4node14dtrace_gc_doneEPN2v87IsolateENS0_6GCTypeENS0_15GCCallbackFlagsEPv:gc-done 429,0</span></code></pre></div></div>
<ul>
<li><code>-n</code> enabled or list probes matching the specified probe name</li>
<li><code>dtrace:::BEGIN { start = timestamp; }</code> The <code>BEGIN</code> probe fires once each time you start a new tracing request. <code>timestamp</code> is a DTrace variable that returns the value of an always incrementing nanosecond counter. We are saving it here to <code>start</code> so we can keep track of the time elapsed since the start of the DTrace tracing request</li>
<li><code>node2008:::gc-start { self-&gt;ts = timestamp; }</code> very similar to what we are doing above but this time saving the timestamp of the <code>node2008:::gc-start</code> probe</li>
<li><code>node2008:::gc-done /self-&gt;ts/ { ... }</code> This fires when GC completes, with a predicate <code>/self-&gt;ts/</code> to ensure we only process gc-done events that have a corresponding gc-start. Let’s break down what happens inside:
<ul>
<li><code>printf("%d,%d\n", (timestamp - start)/1000000, (timestamp - self-&gt;ts)/1000000)</code> Prints two comma-separated values:
<ul>
<li>Time elapsed since tracing started (in milliseconds)</li>
<li>Duration of this GC cycle (in milliseconds)</li>
</ul></li>
<li><code>self-&gt;ts = 0</code> Resets the GC start timestamp for the next cycle</li>
</ul></li>
</ul>
<p>I measured the GC times with DTrace on the modified (backpressure disabled) and unmodified versions of Node.js. For completeness sake, I also measured GC times with the <code>--trace-gc</code> flag as well. Here are the results:</p>
<div id="6cf138ee" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">

<style>
  #altair-viz-5bd73e697da94334b8ccb016dcf9f40a.vega-embed {
    width: 100%;
    display: flex;
  }

  #altair-viz-5bd73e697da94334b8ccb016dcf9f40a.vega-embed details,
  #altair-viz-5bd73e697da94334b8ccb016dcf9f40a.vega-embed details summary {
    position: relative;
  }
</style>
<div id="altair-viz-5bd73e697da94334b8ccb016dcf9f40a"></div>
<script type="text/javascript">
  var VEGA_DEBUG = (typeof VEGA_DEBUG == "undefined") ? {} : VEGA_DEBUG;
  (function(spec, embedOpt){
    let outputDiv = document.currentScript.previousElementSibling;
    if (outputDiv.id !== "altair-viz-5bd73e697da94334b8ccb016dcf9f40a") {
      outputDiv = document.getElementById("altair-viz-5bd73e697da94334b8ccb016dcf9f40a");
    }

    const paths = {
      "vega": "https://cdn.jsdelivr.net/npm/vega@5?noext",
      "vega-lib": "https://cdn.jsdelivr.net/npm/vega-lib?noext",
      "vega-lite": "https://cdn.jsdelivr.net/npm/vega-lite@5.20.1?noext",
      "vega-embed": "https://cdn.jsdelivr.net/npm/vega-embed@6?noext",
    };

    function maybeLoadScript(lib, version) {
      var key = `${lib.replace("-", "")}_version`;
      return (VEGA_DEBUG[key] == version) ?
        Promise.resolve(paths[lib]) :
        new Promise(function(resolve, reject) {
          var s = document.createElement('script');
          document.getElementsByTagName("head")[0].appendChild(s);
          s.async = true;
          s.onload = () => {
            VEGA_DEBUG[key] = version;
            return resolve(paths[lib]);
          };
          s.onerror = () => reject(`Error loading script: ${paths[lib]}`);
          s.src = paths[lib];
        });
    }

    function showError(err) {
      outputDiv.innerHTML = `<div class="error" style="color:red;">${err}</div>`;
      throw err;
    }

    function displayChart(vegaEmbed) {
      vegaEmbed(outputDiv, spec, embedOpt)
        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));
    }

    if(typeof define === "function" && define.amd) {
      requirejs.config({paths});
      let deps = ["vega-embed"];
      require(deps, displayChart, err => showError(`Error loading script: ${err.message}`));
    } else {
      maybeLoadScript("vega", "5")
        .then(() => maybeLoadScript("vega-lite", "5.20.1"))
        .then(() => maybeLoadScript("vega-embed", "6"))
        .catch(showError)
        .then(() => displayChart(vegaEmbed));
    }
  })({"config": {"view": {"continuousWidth": 300, "continuousHeight": 300}}, "data": {"name": "data-e3325b3d8d9378efddc4e46fb430c196"}, "mark": {"type": "line"}, "encoding": {"color": {"field": "configuration", "legend": {"orient": "top"}, "title": "Configuration", "type": "nominal"}, "opacity": {"condition": {"param": "param_1", "value": 1}, "value": 0.2}, "tooltip": [{"field": "configuration", "type": "nominal"}, {"field": "approx_time_ms", "type": "quantitative"}, {"field": "gc_ms", "type": "quantitative"}], "x": {"field": "approx_time_ms", "title": "Approximate Time (ms)", "type": "quantitative"}, "y": {"field": "gc_ms", "title": "GC Duration (ms)", "type": "quantitative"}}, "height": 400, "params": [{"name": "param_1", "select": {"type": "point", "fields": ["configuration"]}, "bind": "legend"}, {"name": "param_2", "select": {"type": "interval", "encodings": ["x", "y"]}, "bind": "scales"}], "title": {"text": "Garbage Collection Duration Over Time", "subtitle": "Click legend items to highlight specific configurations (Shift+click for multiple)"}, "width": 650, "$schema": "https://vega.github.io/schema/vega-lite/v5.20.1.json", "datasets": {"data-e3325b3d8d9378efddc4e46fb430c196": [{"approx_time_ms": 0, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 70, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 71, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 79, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 119, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 120, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 129, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 176, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 176, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 184, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 225, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 226, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 232, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 261, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 267, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 313, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 313, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 321, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 386, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 386, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 395, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 443, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 443, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 451, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 496, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 497, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 505, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 539, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 545, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 581, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 581, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 587, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 626, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 626, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 633, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 675, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 675, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 682, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 734, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 734, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 743, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 779, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 785, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 842, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 842, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 850, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 892, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 899, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 942, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 942, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 948, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 984, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 985, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 994, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1037, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1038, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1045, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1077, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1078, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1086, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1120, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1120, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1127, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1173, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1182, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1221, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1222, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1227, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1280, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1280, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1292, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1350, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1351, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1362, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1396, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1396, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1405, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1432, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1444, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1479, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1484, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1530, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1530, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1552, "gc_ms": 20.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1630, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1630, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1638, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1670, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1670, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1677, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1731, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1731, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1739, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1782, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1782, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1788, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1828, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1828, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1835, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1882, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1882, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1889, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1928, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1928, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1936, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1970, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1970, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1975, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1987, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 1997, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2018, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2021, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2066, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2072, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2076, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2109, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2115, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2116, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2169, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2183, "gc_ms": 13.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2191, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2254, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2254, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2263, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2292, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2308, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2357, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2357, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2372, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2454, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2462, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2466, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2488, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2497, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2543, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2544, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2551, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2597, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2605, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2608, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2653, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2653, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2660, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2689, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2689, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2694, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2733, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2742, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2778, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2778, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2785, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2819, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2819, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2830, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2855, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2864, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2894, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2894, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2905, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2939, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2939, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2950, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2991, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 2991, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3003, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3052, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3052, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3065, "gc_ms": 12.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3086, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3096, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3131, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3131, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3140, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3156, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3165, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3209, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3209, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3219, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3272, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3272, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3280, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3314, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3315, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3320, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3371, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3372, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3382, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3425, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3425, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3446, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3473, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3482, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3528, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3528, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3534, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3577, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3578, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3587, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3620, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3620, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3635, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3687, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3688, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3697, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3753, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3753, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3762, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3805, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3805, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3826, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3879, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3879, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3900, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3952, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3952, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 3962, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4008, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4008, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4020, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4055, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4064, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4112, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4112, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4119, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4152, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4162, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4193, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4212, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4304, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4304, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4310, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4342, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4342, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4349, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4379, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4387, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4417, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4417, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4426, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4512, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4512, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4525, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4569, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4570, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4581, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4621, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4621, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4635, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4671, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4671, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4686, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4718, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4719, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4734, "gc_ms": 13.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4768, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4769, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4779, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4815, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4815, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4825, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4866, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4866, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4872, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4912, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4912, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4920, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4970, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4970, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 4986, "gc_ms": 12.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5025, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5025, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5039, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5082, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5082, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5093, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5133, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5133, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5145, "gc_ms": 10.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5177, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5177, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5184, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5188, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5225, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5225, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5236, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5279, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5279, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5296, "gc_ms": 12.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5344, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5344, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5355, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5398, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5398, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5410, "gc_ms": 11.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5452, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5453, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5465, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5500, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5500, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5510, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5548, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5548, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5562, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5597, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5598, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5612, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5632, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5650, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5692, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5692, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5701, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5741, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5752, "gc_ms": 9.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5776, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5785, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5829, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5829, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5846, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5886, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5886, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5904, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5942, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5943, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5951, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 5985, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6001, "gc_ms": 14.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6041, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6041, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6050, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6096, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6096, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6106, "gc_ms": 9.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6137, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6151, "gc_ms": 10.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6186, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6186, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6197, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6233, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6234, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6248, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6283, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6283, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6294, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6340, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6342, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6362, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6398, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6399, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6404, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6433, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6433, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6443, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6473, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6473, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6507, "gc_ms": 23.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6563, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6563, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6578, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6724, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6724, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6732, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6829, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6829, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6837, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6910, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6910, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6920, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6953, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6953, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6965, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6995, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 6995, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7004, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7021, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7029, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7126, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7126, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7139, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7202, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7202, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7222, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7326, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7326, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7337, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7368, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7368, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7376, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7546, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7546, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7556, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7600, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7600, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7609, "gc_ms": 9.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7670, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7679, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7719, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7719, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7734, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7770, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7771, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7781, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7833, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7833, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7847, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7882, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7883, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7894, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7940, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7940, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 7954, "gc_ms": 13.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8015, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8015, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8026, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8089, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8089, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8112, "gc_ms": 21.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8209, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8210, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8226, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8267, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8267, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8282, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8323, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8324, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8334, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8373, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8373, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8385, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8419, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8419, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8428, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8458, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8458, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8473, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8489, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8595, "gc_ms": 105.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8614, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8631, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8667, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8667, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8684, "gc_ms": 10.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8725, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8725, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8735, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8766, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8766, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8779, "gc_ms": 11.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8876, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8883, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8967, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8967, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 8974, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9047, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9047, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9058, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9155, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9162, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9227, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9228, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9236, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9333, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9334, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9341, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9409, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9422, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9449, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9449, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9456, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9490, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9490, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9499, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9538, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9538, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9551, "gc_ms": 10.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9645, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9645, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9651, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9655, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9757, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9757, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9764, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9878, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9878, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9880, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9887, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9989, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 9989, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10024, "gc_ms": 25.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10244, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10244, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10258, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10466, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10467, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10476, "gc_ms": 9.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10570, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10578, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10728, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10729, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10748, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10861, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10861, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10870, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10957, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10957, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 10965, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11138, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11138, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11147, "gc_ms": 6.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11353, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11371, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11420, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11420, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11531, "gc_ms": 82.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11893, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11894, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11911, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11976, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 11976, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12154, "gc_ms": 178.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12201, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12216, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12244, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12244, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12247, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12253, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12284, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12321, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 12436, "gc_ms": 92.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 14022, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 14031, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 15664, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 15678, "gc_ms": 12.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 16569, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 16570, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 16576, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 17302, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 17303, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 17311, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18016, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18017, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18023, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18699, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18700, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18709, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18897, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 18912, "gc_ms": 14.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 19605, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 19605, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 19611, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 20325, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 20326, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 20343, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21059, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21059, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21064, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21755, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21756, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 21762, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 22334, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 22341, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 23548, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 23549, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 23555, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 24279, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 24279, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 24286, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25005, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25006, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25012, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25715, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25715, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 25721, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 26429, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 26429, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 26434, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27118, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27119, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27128, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27819, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27820, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 27826, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 28510, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 28511, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 28519, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29174, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29175, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29181, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29859, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29860, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 29865, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 30520, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 30521, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 30527, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31218, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31219, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31224, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31895, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31895, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 31900, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 32573, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 32574, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 32580, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33261, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33262, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33267, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33966, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33967, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 33972, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 34643, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 34643, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 34649, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 35355, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 35356, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 35361, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36029, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36030, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36034, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36704, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36705, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 36710, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 37378, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 37379, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 37386, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38066, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38067, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38072, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38733, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38734, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 38739, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 39424, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 39424, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 39430, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40096, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40096, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40104, "gc_ms": 7.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40772, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40772, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 40778, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 41469, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 41470, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 41475, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42159, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42159, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42164, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42883, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42884, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 42889, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 43645, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 43645, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 43651, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 44326, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 44327, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 44337, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45063, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45065, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45074, "gc_ms": 8.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45794, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45794, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 45799, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 46484, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 46485, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 46490, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47179, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47180, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47185, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47906, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47906, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 47919, "gc_ms": 11.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 48591, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 48592, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 48597, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49282, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49283, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49289, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49994, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49995, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 49999, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 50509, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 50513, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51218, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51224, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51419, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51423, "gc_ms": 3.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51722, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 51728, "gc_ms": 1.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 52431, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 52432, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 52436, "gc_ms": 2.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 52812, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 52818, "gc_ms": 5.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 53207, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 53212, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 53959, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 53960, "gc_ms": 0.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 53966, "gc_ms": 4.0, "configuration": "Modified (DTrace)"}, {"approx_time_ms": 41, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 51, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 71, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 93, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 118, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 129, "gc_ms": 1.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 161, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 163, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 193, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 197, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 199, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 233, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 234, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 256, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 259, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 260, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 284, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 285, "gc_ms": 0.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 317, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 321, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 323, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 366, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 370, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 435, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 442, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 446, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 486, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 490, "gc_ms": 0.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 539, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 548, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 550, "gc_ms": 1.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 594, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 597, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 643, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 652, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 655, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 698, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 703, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 746, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 753, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 757, "gc_ms": 1.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 802, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 805, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 839, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 846, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 850, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 890, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 892, "gc_ms": 0.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 915, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 950, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 952, "gc_ms": 0.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 987, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 991, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 993, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1030, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1032, "gc_ms": 0.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1069, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1074, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1076, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1113, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1117, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1161, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1170, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1173, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1227, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1232, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1274, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1280, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1283, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1317, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1320, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1359, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1364, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1368, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1490, "gc_ms": 2.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1505, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1567, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1572, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1576, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1621, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1624, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1670, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1677, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1680, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1730, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1734, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1771, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1776, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1779, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1843, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1847, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1892, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1899, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1902, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1940, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1944, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1983, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1990, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 1992, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2030, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2033, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2073, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2077, "gc_ms": 0.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2080, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2107, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2143, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2145, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2169, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2196, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2198, "gc_ms": 1.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2222, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2225, "gc_ms": 2.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2261, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2264, "gc_ms": 2.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2291, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2293, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2318, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2320, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2342, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2344, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2366, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2368, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2400, "gc_ms": 1.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2429, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2432, "gc_ms": 3.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2452, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2475, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2477, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2500, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2502, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2524, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2526, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2548, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2551, "gc_ms": 1.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2574, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2577, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2598, "gc_ms": 0.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2601, "gc_ms": 2.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2625, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2629, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2653, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2658, "gc_ms": 3.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2681, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2684, "gc_ms": 1.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2708, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2710, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2731, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2736, "gc_ms": 3.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2745, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2765, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2768, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2776, "gc_ms": 1.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2784, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2805, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2808, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2829, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2831, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2845, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2856, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2869, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2891, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2894, "gc_ms": 1.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2915, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2917, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2938, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2940, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2956, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 2980, "gc_ms": 1.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3000, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3003, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3023, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3025, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3045, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3047, "gc_ms": 1.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3067, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3069, "gc_ms": 1.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3081, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3104, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3108, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3133, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3137, "gc_ms": 1.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3158, "gc_ms": 1.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3560, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3574, "gc_ms": 4.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3872, "gc_ms": 1.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3925, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3930, "gc_ms": 4.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 3994, "gc_ms": 1.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4138, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4142, "gc_ms": 1.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4396, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4400, "gc_ms": 1.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4422, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4497, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4500, "gc_ms": 1.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4581, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4611, "gc_ms": 2.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4642, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4646, "gc_ms": 1.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4672, "gc_ms": 1.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4702, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4706, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4740, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4745, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4776, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4780, "gc_ms": 2.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4826, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4830, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4920, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4924, "gc_ms": 1.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 4965, "gc_ms": 2.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5004, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5009, "gc_ms": 2.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5033, "gc_ms": 5.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5066, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5070, "gc_ms": 1.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5097, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5101, "gc_ms": 1.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5161, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5166, "gc_ms": 1.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5209, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5214, "gc_ms": 1.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5269, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5274, "gc_ms": 1.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5313, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5318, "gc_ms": 1.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5363, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5368, "gc_ms": 3.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5407, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5413, "gc_ms": 1.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5446, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5450, "gc_ms": 1.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5479, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5483, "gc_ms": 3.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5511, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5515, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5610, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5615, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5652, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5657, "gc_ms": 1.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5696, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5700, "gc_ms": 3.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5736, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5741, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5775, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5780, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5824, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5829, "gc_ms": 4.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5885, "gc_ms": 2.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5923, "gc_ms": 2.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5966, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 5973, "gc_ms": 1.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6101, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6110, "gc_ms": 6.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6150, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6155, "gc_ms": 1.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6187, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6193, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6227, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6232, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6263, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6269, "gc_ms": 5.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6315, "gc_ms": 3.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6428, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6439, "gc_ms": 5.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6481, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6489, "gc_ms": 2.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6636, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6664, "gc_ms": 3.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6726, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6739, "gc_ms": 3.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6813, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6822, "gc_ms": 2.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6886, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6891, "gc_ms": 3.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6955, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 6974, "gc_ms": 7.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7043, "gc_ms": 8.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7097, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7111, "gc_ms": 7.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7227, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7239, "gc_ms": 1.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7284, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7292, "gc_ms": 2.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7333, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7344, "gc_ms": 9.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7388, "gc_ms": 3.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7459, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7469, "gc_ms": 3.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7518, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7523, "gc_ms": 1.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7581, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7600, "gc_ms": 5.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7660, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7711, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7719, "gc_ms": 2.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7763, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7769, "gc_ms": 1.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7812, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7819, "gc_ms": 3.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7861, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7868, "gc_ms": 2.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7934, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7942, "gc_ms": 5.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 7995, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8000, "gc_ms": 1.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8042, "gc_ms": 2.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8078, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8083, "gc_ms": 2.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8107, "gc_ms": 1.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8137, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8144, "gc_ms": 2.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8183, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8190, "gc_ms": 3.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8227, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8235, "gc_ms": 1.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8275, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8284, "gc_ms": 3.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8318, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8323, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8352, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8360, "gc_ms": 3.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8392, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8399, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8465, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8471, "gc_ms": 6.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8505, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8513, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8546, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8552, "gc_ms": 2.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8615, "gc_ms": 2.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8637, "gc_ms": 2.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8709, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8722, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8767, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8778, "gc_ms": 3.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8886, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8898, "gc_ms": 4.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8939, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8946, "gc_ms": 2.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8979, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8989, "gc_ms": 3.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9038, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9056, "gc_ms": 3.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9121, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9127, "gc_ms": 3.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9187, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9197, "gc_ms": 9.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9250, "gc_ms": 4.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9321, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9328, "gc_ms": 6.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9427, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9433, "gc_ms": 1.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9495, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9500, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9585, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9602, "gc_ms": 8.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9694, "gc_ms": 4.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9778, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9790, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9862, "gc_ms": 1.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 9869, "gc_ms": 1.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10000, "gc_ms": 4.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10023, "gc_ms": 6.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10161, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10173, "gc_ms": 5.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10228, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10283, "gc_ms": 1.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10364, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10377, "gc_ms": 3.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10463, "gc_ms": 2.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10517, "gc_ms": 7.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10615, "gc_ms": 3.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10643, "gc_ms": 6.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10879, "gc_ms": 2.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10896, "gc_ms": 6.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10964, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 10970, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11069, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11076, "gc_ms": 3.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11128, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11138, "gc_ms": 2.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11281, "gc_ms": 3.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11308, "gc_ms": 4.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11392, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11399, "gc_ms": 4.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11472, "gc_ms": 1.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11484, "gc_ms": 4.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11549, "gc_ms": 3.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11570, "gc_ms": 5.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11813, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 11844, "gc_ms": 4.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12016, "gc_ms": 9.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12182, "gc_ms": 1.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12197, "gc_ms": 5.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12299, "gc_ms": 4.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12406, "gc_ms": 1.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12418, "gc_ms": 9.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12483, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12489, "gc_ms": 2.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12613, "gc_ms": 4.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12678, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12686, "gc_ms": 2.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12751, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12766, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12842, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12850, "gc_ms": 6.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12915, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12922, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12987, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 12996, "gc_ms": 7.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13075, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13088, "gc_ms": 0.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13150, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13171, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13468, "gc_ms": 5.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13817, "gc_ms": 5.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13958, "gc_ms": 1.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 13998, "gc_ms": 6.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14307, "gc_ms": 4.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14495, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14541, "gc_ms": 7.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14682, "gc_ms": 3.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14815, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14835, "gc_ms": 6.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14931, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 14951, "gc_ms": 5.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15020, "gc_ms": 1.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15040, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15130, "gc_ms": 7.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15157, "gc_ms": 7.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15238, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15274, "gc_ms": 6.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15360, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15376, "gc_ms": 5.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15456, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15481, "gc_ms": 3.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15550, "gc_ms": 3.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15639, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15668, "gc_ms": 5.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15771, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 15818, "gc_ms": 2.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16041, "gc_ms": 8.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16185, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16197, "gc_ms": 4.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16290, "gc_ms": 5.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16403, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16443, "gc_ms": 7.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16635, "gc_ms": 1.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16665, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16721, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16733, "gc_ms": 2.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16768, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16775, "gc_ms": 6.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16828, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16846, "gc_ms": 5.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16941, "gc_ms": 2.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 16994, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17076, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17090, "gc_ms": 7.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17129, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17141, "gc_ms": 3.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17202, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17216, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17276, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17344, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17357, "gc_ms": 9.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17394, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17404, "gc_ms": 5.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17465, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17476, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17533, "gc_ms": 6.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17601, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17608, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17681, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17699, "gc_ms": 4.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17818, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17838, "gc_ms": 5.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17885, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17899, "gc_ms": 3.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17961, "gc_ms": 1.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 17983, "gc_ms": 0.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18018, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18029, "gc_ms": 9.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18069, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18078, "gc_ms": 1.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18128, "gc_ms": 8.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18172, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18197, "gc_ms": 6.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18235, "gc_ms": 1.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18244, "gc_ms": 7.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18274, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18280, "gc_ms": 5.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18313, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18324, "gc_ms": 4.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18351, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18365, "gc_ms": 6.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18407, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18421, "gc_ms": 4.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18460, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18489, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18498, "gc_ms": 8.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18531, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18541, "gc_ms": 2.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18574, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18589, "gc_ms": 2.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18624, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18660, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18677, "gc_ms": 5.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18713, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18721, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18722, "gc_ms": 1.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18767, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18776, "gc_ms": 7.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18809, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18854, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 18974, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19020, "gc_ms": 5.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19135, "gc_ms": 5.25, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19256, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19328, "gc_ms": 3.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19370, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19381, "gc_ms": 0.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19427, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19438, "gc_ms": 2.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19512, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19522, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19582, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19599, "gc_ms": 6.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19646, "gc_ms": 1.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19730, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19743, "gc_ms": 3.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19847, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19871, "gc_ms": 2.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19901, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19910, "gc_ms": 8.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19942, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19954, "gc_ms": 5.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19986, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 19999, "gc_ms": 0.88, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20029, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20039, "gc_ms": 2.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20077, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20092, "gc_ms": 4.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20147, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20213, "gc_ms": 7.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20286, "gc_ms": 0.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20303, "gc_ms": 5.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20340, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20350, "gc_ms": 9.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20382, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20392, "gc_ms": 7.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20423, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20434, "gc_ms": 8.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20468, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20483, "gc_ms": 5.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20511, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20524, "gc_ms": 5.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20557, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20575, "gc_ms": 5.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20604, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20618, "gc_ms": 8.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20648, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20658, "gc_ms": 1.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20690, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20703, "gc_ms": 3.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20746, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20759, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20815, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20833, "gc_ms": 5.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20869, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20876, "gc_ms": 4.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20934, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20943, "gc_ms": 9.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 20989, "gc_ms": 3.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21085, "gc_ms": 2.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21127, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21134, "gc_ms": 4.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21198, "gc_ms": 1.08, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21209, "gc_ms": 3.12, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21242, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21255, "gc_ms": 2.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21304, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21318, "gc_ms": 1.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21353, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21363, "gc_ms": 2.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21399, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21411, "gc_ms": 3.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21444, "gc_ms": 0.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21455, "gc_ms": 2.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 21513, "gc_ms": 3.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 22219, "gc_ms": 4.79, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 22612, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 23290, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 23998, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 24003, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 24483, "gc_ms": 4.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 25175, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 25182, "gc_ms": 5.96, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 25856, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 25863, "gc_ms": 1.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 26564, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 26571, "gc_ms": 2.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 27289, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 27296, "gc_ms": 1.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 27972, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 27977, "gc_ms": 4.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 28666, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 28672, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 29366, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 29373, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 30044, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 30052, "gc_ms": 2.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 30780, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 30790, "gc_ms": 6.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 31460, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 31466, "gc_ms": 4.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 32140, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 32146, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 32886, "gc_ms": 0.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 32894, "gc_ms": 4.0, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 33685, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 33691, "gc_ms": 4.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 34375, "gc_ms": 0.33, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 34381, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 35085, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 35091, "gc_ms": 5.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 35777, "gc_ms": 0.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 35786, "gc_ms": 2.17, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 36516, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 36524, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 37192, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 37198, "gc_ms": 1.29, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 37989, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 37995, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 38682, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 38688, "gc_ms": 1.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 39382, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 39388, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 40038, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 40044, "gc_ms": 2.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 40762, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 40772, "gc_ms": 8.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 41447, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 41454, "gc_ms": 3.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 42128, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 42134, "gc_ms": 5.04, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 42932, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 42946, "gc_ms": 2.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 43655, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 43660, "gc_ms": 0.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 44392, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 44403, "gc_ms": 1.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 45132, "gc_ms": 0.71, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 45137, "gc_ms": 0.67, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 45845, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 45852, "gc_ms": 4.92, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 46577, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 46583, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 47296, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 47302, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 48023, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 48028, "gc_ms": 3.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 48746, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 48753, "gc_ms": 1.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 49448, "gc_ms": 0.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 49458, "gc_ms": 0.75, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 50149, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 50155, "gc_ms": 1.5, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 50843, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 50851, "gc_ms": 6.21, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 51587, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 51594, "gc_ms": 1.58, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 52282, "gc_ms": 0.42, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 52287, "gc_ms": 0.83, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 53021, "gc_ms": 0.62, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 53027, "gc_ms": 1.54, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 53768, "gc_ms": 0.38, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 53773, "gc_ms": 1.46, "configuration": "Modified (Trace GC)"}, {"approx_time_ms": 8, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 115, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 237, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 337, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 446, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 545, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 644, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 741, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 838, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 933, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1028, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1128, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1227, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1328, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1422, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1516, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1615, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1716, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1820, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 1920, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2015, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2114, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2211, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2304, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2402, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2514, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2611, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2710, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2812, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 2911, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3003, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3101, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3201, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3300, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3398, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3500, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3597, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3696, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3793, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3892, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 3991, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4089, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4187, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4283, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4381, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4476, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4578, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4675, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4770, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4862, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 4957, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5053, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5151, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5256, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5354, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5449, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5543, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5638, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5734, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5826, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 5924, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6020, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6120, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6216, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6317, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6418, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6518, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6646, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6742, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6841, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 6942, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7040, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7138, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7232, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7326, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7421, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7516, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7610, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7704, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7796, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7894, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 7994, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8089, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8186, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8284, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8385, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8483, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8586, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8682, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8782, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8880, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 8978, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9072, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9170, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9269, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9464, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9660, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 9848, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 10039, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 10234, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 10420, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 10621, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 10821, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11014, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11212, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11404, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11591, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11776, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 11971, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 12169, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 12367, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 12571, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 12776, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 12967, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 13157, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 13349, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 13546, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 13732, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 13922, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 14116, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 14307, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 14500, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 14710, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 14908, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 15106, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 15312, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 15508, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 15703, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 15896, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 16087, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 16280, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 16479, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 16676, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 16900, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 17093, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 17386, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 17587, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 17785, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 17984, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 18181, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 18379, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 18570, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 18761, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 18958, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 19151, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 19349, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 19548, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 19742, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 19947, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 20143, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 20341, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 20537, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 20728, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 20930, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 21123, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 21320, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 21514, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 21710, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 21900, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 22090, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 22290, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 22489, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 22688, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 22898, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 23103, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 23301, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 23501, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 23697, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 23884, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 24071, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 24263, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 24460, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 24654, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 24852, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 25045, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 25243, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 25435, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 25626, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 25809, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26003, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26198, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26392, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26583, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26778, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 26978, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 27172, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 27364, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 27566, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 27763, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 27954, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 28142, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 28330, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 28531, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 28727, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 28936, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 29301, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 29559, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 29750, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 29938, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 30124, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 30310, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 30490, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 30664, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 30845, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 31057, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 31276, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 31481, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 31675, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 31873, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 32071, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 32272, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 32471, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 32665, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 32858, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 33056, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 33247, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 33441, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 33632, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 33827, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34026, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34214, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34407, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34604, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34797, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 34989, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 35194, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 35389, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 35576, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 35772, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 35968, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 36165, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 36360, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 36553, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 36744, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 36936, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 37146, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 37341, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 37542, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 37724, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 37921, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 38117, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 38304, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 38501, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 38694, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 38898, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 39113, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 39308, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 39502, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 39696, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 39891, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40089, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40288, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40480, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40667, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40859, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 41049, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 41252, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 41447, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 41639, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 41830, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42026, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42216, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42407, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42597, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42799, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 42989, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 43187, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 43386, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 43580, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 43777, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 43969, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 44157, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 44353, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 44547, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 44743, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 44930, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 45120, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 45327, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 45519, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 45710, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 45896, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 46100, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 46297, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 46490, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 46674, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 46870, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 47063, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 47272, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 47471, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 47670, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 47870, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 48062, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 48253, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 48441, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 48638, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 48841, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 49039, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 49263, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 49466, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 49656, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 49870, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 50068, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 50265, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 50460, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 50653, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 50854, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 51051, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 51269, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 51466, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 51661, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 51862, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 52063, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 52257, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 52452, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 52646, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 52839, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 53036, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 53237, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 53443, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 53643, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 53840, "gc_ms": 0.0, "configuration": "Unmodified (DTrace)"}, {"approx_time_ms": 40, "gc_ms": 0.58, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 101, "gc_ms": 0.71, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 187, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 272, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 335, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 413, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 498, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 595, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 709, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 805, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 898, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 995, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1090, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1187, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1282, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1378, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1469, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1563, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1659, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1766, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1864, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 1958, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2059, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2157, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2256, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2359, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2455, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2548, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2650, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2759, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2859, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 2959, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3055, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3150, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3247, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3335, "gc_ms": 1.96, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3433, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3530, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3624, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3753, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3853, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 3950, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4051, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4153, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4253, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4362, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4463, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4564, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4665, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4793, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4893, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 4991, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5088, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5188, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5284, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5385, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5480, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5580, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5682, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5794, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5892, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 5993, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6094, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6193, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6290, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6392, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6489, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6582, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6680, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6783, "gc_ms": 0.21, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6885, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 6983, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7094, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7195, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7300, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7396, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7492, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7594, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7692, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7798, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7899, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 7996, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8098, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8205, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8306, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8417, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8518, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8617, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8715, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8831, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 8931, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9030, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9125, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9221, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9313, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9408, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9500, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9597, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9696, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9796, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 9905, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10001, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10100, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10197, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10293, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10393, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10505, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10602, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10702, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10803, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 10913, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11013, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11116, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11215, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11315, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11414, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11513, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11610, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11708, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11806, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 11920, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12013, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12110, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12207, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12303, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12400, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12509, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12606, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12706, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12804, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 12913, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13009, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13111, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13210, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13305, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13408, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13502, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13597, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13695, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13796, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 13924, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14036, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14136, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14234, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14329, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14424, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14628, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 14829, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 15041, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 15237, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 15434, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 15632, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 15831, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 16043, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 16236, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 16426, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 16630, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 16828, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 17036, "gc_ms": 0.38, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 17238, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 17435, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 17631, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 17820, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 18018, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 18225, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 18415, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 18618, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 18813, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 19009, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 19245, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 19441, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 19642, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 19840, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 20041, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 20254, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 20452, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 20656, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 20855, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 21052, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 21264, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 21468, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 21667, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 21865, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 22059, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 22273, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 22471, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 22677, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 22874, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 23072, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 23272, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 23461, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 23661, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 23855, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 24054, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 24294, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 24492, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 24701, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 24903, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 25098, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 25310, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 25500, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 25694, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 25891, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 26086, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 26293, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 26491, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 26685, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 26898, "gc_ms": 0.29, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 27089, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 27297, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 27497, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 27700, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 27903, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 28119, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 28326, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 28518, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 28710, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 28912, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 29106, "gc_ms": 0.21, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 29358, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 29551, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 29754, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 29957, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 30157, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 30362, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 30554, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 30749, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 30954, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 31151, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 31354, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 31554, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 31753, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 31946, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 32155, "gc_ms": 0.21, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 32364, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 32562, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 32760, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 32964, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 33152, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 33361, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 33560, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 33758, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 33955, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 34164, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 34394, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 34592, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 34779, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 34962, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 35145, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 35326, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 35522, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 35714, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 35907, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 36099, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 36294, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 36494, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 36698, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 36907, "gc_ms": 0.21, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 37108, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 37303, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 37506, "gc_ms": 0.21, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 37699, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 37891, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 38090, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 38291, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 38489, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 38703, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 38916, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 39116, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 39314, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 39535, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 39754, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 39951, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 40148, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 40338, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 40561, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 40759, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 40962, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 41162, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 41359, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 41573, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 41768, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 41967, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 42167, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 42367, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 42568, "gc_ms": 0.29, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 42784, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 42992, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 43187, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 43391, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 43599, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 43804, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 44000, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 44195, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 44397, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 44637, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 44851, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 45065, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 45269, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 45468, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 45675, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 45867, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 46063, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 46262, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 46461, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 46671, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 46870, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 47086, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 47277, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 47466, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 47664, "gc_ms": 0.17, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 47867, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 48068, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 48305, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 48501, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 48727, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 48927, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 49143, "gc_ms": 0.25, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 49345, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 49554, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 49806, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 50004, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 50212, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 50410, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 50610, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 50820, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 51018, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 51226, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 51435, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 51631, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 51833, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 52028, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 52223, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 52417, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 52613, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 52818, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 53016, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 53221, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 53416, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 53616, "gc_ms": 0.08, "configuration": "Unmodified (Trace GC)"}, {"approx_time_ms": 53826, "gc_ms": 0.12, "configuration": "Unmodified (Trace GC)"}]}}, {"mode": "vega-lite"});
</script>
</div>
</div>
<p>Now, I wouldn’t take the numbers too seriously as I have broken many benchmarking sins here, but the general takeaway is true regardless. Disabling backpressure clearly makes the GC work much harder.</p>
<p>This was interesting to see, but it has me left wondering, how does the Node.js backpressure mechanism work? Well, this gets explained later on in the docs.</p>
<p>Essentially, when a <code>false</code> is returned from the <code>writeOrBuffer()</code>, it will pause the <code>Readable</code> stream from sending any data and wait until the consumer is ready again, which gets notified by the <code>drain</code> event. The <code>writeOrBuffer()</code> function will return <code>false</code> when the data buffer has exceeded the <a href="https://nodejs.org/api/stream.html#stream_buffering">highWaterMark</a> or the write queue is internally busy.</p>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-4-contents" aria-controls="callout-4" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Caution
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-4" class="callout-4-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>This explanation is based on the current Node.js docs at the time of writing. It looks like the <code>writeOrBuffer()</code> function may have additional logic now compared to older <code>write()</code> function, so behavior could differ depending on your Node.js version.</p>
</div>
</div>
</div>
<p>Hopefully, this post demystifies a bit of how backpressure works in Node.js and how you can use DTrace to measure GC. Now it’s time to go watch Big Buck Bunny!</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-dtrace/</guid>
  <pubDate>Sun, 19 Oct 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries Git Bisect</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-git-bisect/</link>
  <description><![CDATA[ 




<hr>
<p>I want to walk through how I went about debugging this <a href="https://github.com/supabase/storage/issues/771">issue</a> and how <code>git bisect</code> was crucial for pinpointing the exact commit that caused it.</p>
<p>First, I tried to reproduce the issue locally on my machine. The user <a href="https://github.com/Cap-go/capgo/actions/runs/17979805447/job/51142531945">linked</a> the GitHub action where they first noticed this issue occurring. I was able to look at the logs to find out the version of supabase storage they were running <code>Downloaded newer image for ghcr.io/supabase/storage-api:v1.27.4</code>. Now that I know the version I checked out that specific commit and ran the storage api locally.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">master</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> </span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git checkout v1.27.4</span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> </span>
<span id="cb1-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npm run infra:start</span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> </span>
<span id="cb1-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npm run dev</span></code></pre></div></div>
<p>With the server running, I copied the repro script from the GitHub issue to my local environment. The script required an additional package, so I temporarily added it to the package.json just to get the script working locally, not as a permanent dependency.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> </span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx jsr add @bradenmacdonald/s3-lite-client</span></code></pre></div></div>
<p>I changed some of the hardcoded defaults because it was setup to run against the supabase cli and I also added some code to handle creating the bucket and uploading the example file for convenience.</p>
<p>After running the script this was the result.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> node src/scripts/repro.ts</span>
<span id="cb3-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Creating</span> bucket: your-bucket</span>
<span id="cb3-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Bucket</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your-bucket'</span> already exists</span>
<span id="cb3-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Uploading</span> file to: orgs/demo-app/example.txt</span>
<span id="cb3-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> uploaded successfully to orgs/demo-app/example.txt</span>
<span id="cb3-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Presigned</span> PUT URL: http://127.0.0.1:5000/s3/your-bucket/orgs/demo-app/example.txt<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span>X-Amz-Content-Sha256=UNSIGNED-PAYLOAD<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">x-id=PutObject</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Algorithm=AWS4-HMAC-SHA256</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Credential=b585f311d839730f8a980a3457be2787%2F20251004%2Fus-east-1%2Fs3%2Faws4_request</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Date=20251004T193230Z</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Expires=60</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-SignedHeaders=host</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Signature=75b7bd2d33b66855952bad41bc56f17aaa98cd96a50f49ad96540c030e27ee19</span></span>
<span id="cb3-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Local</span> storage response: 200</span>
<span id="cb3-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Response</span> body:</span></code></pre></div></div>
<p>Huh, completed successfully. This had me puzzled but then I recalled the user was running into issues when running with the supabase cli command. So, instead of running directly against the storage api I thought I try against the supabase cli.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx supabase init</span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx supabase start</span></code></pre></div></div>
<p>I reran the script.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb5-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> node src/scripts/repro.ts</span>
<span id="cb5-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Creating</span> bucket: your-bucket</span>
<span id="cb5-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Bucket</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your-bucket'</span> already exists</span>
<span id="cb5-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Uploading</span> file to: orgs/demo-app/example.txt</span>
<span id="cb5-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> uploaded successfully to orgs/demo-app/example.txt</span>
<span id="cb5-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Presigned</span> PUT URL: http://127.0.0.1:5000/s3/your-bucket/orgs/demo-app/example.txt<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span>X-Amz-Content-Sha256=UNSIGNED-PAYLOAD<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">x-id=PutObject</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Algorithm=AWS4-HMAC-SHA256</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Credential=b585f311d839730f8a980a3457be2787%2F20251004%2Fus-east-1%2Fs3%2Faws4_request</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Date=20251004T193230Z</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Expires=60</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-SignedHeaders=host</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Signature=75b7bd2d33b66855952bad41bc56f17aaa98cd96a50f49ad96540c030e27ee19</span></span>
<span id="cb5-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Local</span> storage response: 200</span>
<span id="cb5-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Response</span> body:</span></code></pre></div></div>
<p>What!? Succeeded again. Then I realized the user was running supabase cli version 2.45.5 so I tried it again.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> npx supabase@2.45.5 start</span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">work/storage</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">v1.27.4</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> node src/scripts/repro.ts</span>
<span id="cb6-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Creating</span> bucket: your-bucket</span>
<span id="cb6-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Bucket</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your-bucket'</span> created successfully</span>
<span id="cb6-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Uploading</span> file to: orgs/demo-app/example.txt</span>
<span id="cb6-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">File</span> uploaded successfully to orgs/demo-app/example.txt</span>
<span id="cb6-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Presigned</span> PUT URL: http://127.0.0.1:54321/storage/v1/s3/your-bucket/orgs/demo-app/example.txt<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span>X-Amz-Content-Sha256=UNSIGNED-PAYLOAD<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">x-id=PutObject</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Algorithm=AWS4-HMAC-SHA256</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Credential=625729a08b95bf1b7ff351a663f3a23c%2F20251004%2Flocal%2Fs3%2Faws4_request</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Date=20251004T201956Z</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Expires=60</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-SignedHeaders=host</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X-Amz-Signature=1f2ff5cca5aad73d7e1e53224e6b6a3f96f89bbf144a3cdebc2ef9825d15c7de</span></span>
<span id="cb6-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Local</span> storage response: 400</span>
<span id="cb6-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Response</span> body: <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span>xml version=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1.0"</span> encoding=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UTF-8"</span> standalone=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"yes"</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span>Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span>Resource<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>your-bucket/orgs/demo-app/example.txt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>/Resource<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span>Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>InvalidSignature<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>/Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span>Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>Unsupported authorization type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>/Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span>/Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<p>Bingo! So this tells me it has to be an issue with the supabase cli and it was already fixed in the most recent version. But how do I figure out what change caused the issue and what changed fixed it?</p>
<p><code>git bisect</code> baby. Git bisect is a tool that runs a binary search to find the commit that introduced a bug. You give it a good commit, bad commit, a script to run and it will take care of the rest.</p>
<p>I checked the <a href="https://github.com/Cap-go/capgo/actions/workflows/tests.yml">capgo</a> “Run tests” GitHub Action to see that last time it succeeded to figure out the last known working version. Looks like last time the GHA passed was supabase cli version <code>2.40.7</code></p>
<p>I cloned the supabase cli repo into a dedicated repro directory.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">code/work/debugging/repro-presigned-url-local-771</span></span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git clone https://github.com/supabase/cli.git</span></code></pre></div></div>
<p>I had Copilot generate a quick bash script I could use with git bisect</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/bin/bash</span></span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-e</span></span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get the current directory (should be the CLI repo)</span></span>
<span id="cb8-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CLI_DIR</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pwd</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">TEST_DIR</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/Users/tyler/code/work/debugging/repro-presigned-url-local-771"</span></span>
<span id="cb8-8"></span>
<span id="cb8-9"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Building CLI at commit </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> rev-parse <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--short</span> HEAD<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">..."</span></span>
<span id="cb8-10"></span>
<span id="cb8-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Build the CLI</span></span>
<span id="cb8-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">go</span> build <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> supabase_cli main.go</span>
<span id="cb8-13"></span>
<span id="cb8-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Stop any existing supabase instance</span></span>
<span id="cb8-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">./supabase_cli</span> stop <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-backup</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb8-16"></span>
<span id="cb8-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wait a moment for cleanup</span></span>
<span id="cb8-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sleep</span> 2</span>
<span id="cb8-19"></span>
<span id="cb8-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Start supabase with your specific exclusions</span></span>
<span id="cb8-21"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Starting Supabase services..."</span></span>
<span id="cb8-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">./supabase_cli</span> start <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-x</span> imgproxy,studio,mailpit,realtime,postgres-meta,supavisor,studio,logflare,vector,realtime,gotrue,edge-runtime</span>
<span id="cb8-23"></span>
<span id="cb8-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wait for services to be ready</span></span>
<span id="cb8-25"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Waiting for services to start..."</span></span>
<span id="cb8-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sleep</span> 15</span>
<span id="cb8-27"></span>
<span id="cb8-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Run the test</span></span>
<span id="cb8-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Running presigned URL test..."</span></span>
<span id="cb8-30"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$TEST_DIR</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb8-31"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pnpm</span> run dev</span>
<span id="cb8-32"></span>
<span id="cb8-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Capture the exit code</span></span>
<span id="cb8-34"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">result</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$?</span></span>
<span id="cb8-35"></span>
<span id="cb8-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Stop supabase</span></span>
<span id="cb8-37"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stopping Supabase services..."</span></span>
<span id="cb8-38"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$CLI_DIR</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb8-39"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">./supabase_cli</span> stop <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-backup</span></span>
<span id="cb8-40"></span>
<span id="cb8-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return result (0 = good/success, non-zero = bad/failure)</span></span>
<span id="cb8-42"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">[</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$result</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">-eq</span> 0 <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">]</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">then</span></span>
<span id="cb8-43">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"✅ Test PASSED - presigned URL works"</span></span>
<span id="cb8-44">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">exit</span> 0</span>
<span id="cb8-45"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb8-46">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"❌ Test FAILED - presigned URL broken"</span></span>
<span id="cb8-47">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">exit</span> 1</span>
<span id="cb8-48"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">fi</span></span></code></pre></div></div>
<p>I then started the bisect.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb9-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect start</span>
<span id="cb9-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">status:</span> waiting for both good and bad commits</span>
<span id="cb9-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb9-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect good v2.40.7</span>
<span id="cb9-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">status:</span> waiting for bad commit, 1 good commit known</span>
<span id="cb9-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb9-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect bad v2.45.5</span>
<span id="cb9-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">git</span> bisect run ./test_presigned_url.sh</span>
<span id="cb9-10"></span>
<span id="cb9-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ccec464034cc90832dcb8022f78419929d5e3f7d</span> is the first bad commit</span>
<span id="cb9-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">commit</span> ccec464034cc90832dcb8022f78419929d5e3f7d</span>
<span id="cb9-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Date:</span>   Wed Sep 17 10:03:52 2025 +0800</span>
<span id="cb9-14"></span>
<span id="cb9-15">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">feat:</span> support publishable and secret key locally</span>
<span id="cb9-16"></span>
<span id="cb9-17"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">internal/start/start.go</span>           <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span>  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">9</span> +++++</span>
<span id="cb9-18"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">internal/start/templates/kong.yml</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">71</span> ++++++++++++++++++++++++++++++++++++++-</span>
<span id="cb9-19"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">internal/status/status.go</span>         <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">28</span> ++++++++++++---</span>
<span id="cb9-20"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pkg/config/apikeys.go</span>             <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span>  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">7</span> ++++</span>
<span id="cb9-21"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pkg/config/auth.go</span>                <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span>  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2</span> ++</span>
<span id="cb9-22"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">5</span> files changed, 112 insertions<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">+</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">,</span> 5 deletions<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb9-23"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bisect</span> found first bad commit</span></code></pre></div></div>
<p>Once I found the problematic commit, I wanted to pinpoint exactly when the issue was resolved. To do this, I flipped the logic in my repro script, now it exits with <code>0</code> when the test fails and <code>1</code> when it succeeds. This way, <code>git bisect</code> can help me track down the first commit where things start working again.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb10-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect start</span>
<span id="cb10-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">status:</span> waiting for both good and bad commits</span>
<span id="cb10-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb10-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect good v2.45.5</span>
<span id="cb10-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">status:</span> waiting for bad commit, 1 good commit known</span>
<span id="cb10-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb10-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect bad develop</span>
<span id="cb10-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">debugging/repro-presigned-url-local-771</span> git:<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">main</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✗</span></span>
<span id="cb10-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> git bisect run ./test_presigned_url.sh</span>
<span id="cb10-11"></span>
<span id="cb10-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">f5e1774848af5f97f286cae5d41b2aa3ef050830</span> is the first bad commit</span>
<span id="cb10-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">commit</span> f5e1774848af5f97f286cae5d41b2aa3ef050830</span>
<span id="cb10-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Date:</span>   Thu Sep 25 17:17:29 2025 +0800</span>
<span id="cb10-15"></span>
<span id="cb10-16">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">fix:</span> replace auth header for backwards compatibility</span>
<span id="cb10-17"></span>
<span id="cb10-18"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">internal/start/start.go</span>           <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">11</span> ++++++++---</span>
<span id="cb10-19"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">internal/start/templates/kong.yml</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">28</span> +++++++++++++++-------------</span>
<span id="cb10-20"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2</span> files changed, 23 insertions<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">+</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">,</span> 16 deletions<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb10-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bisect</span> found first bad commit</span></code></pre></div></div>
<p>Ah, the good ole <code>fix:</code> commit. We were able to easily close the issue by letting the user know to upgrade to the most recent version.</p>
<p>Next time you want to find the commit where it all went wrong (or right) try out <code>git bisect</code>.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-git-bisect/</guid>
  <pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Oxide and Friends Change Computing Forever</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/oxide-and-friends/</link>
  <description><![CDATA[ 




<hr>
<blockquote class="blockquote">
<p><strong>Change Computing Forever:</strong></p>
<p>Computing is our shared passion; our calling is to advance the state of the art, bringing those advances to the broadest possible audience.</p>
</blockquote>
<p>This is part of Oxide’s <a href="https://oxide.computer/principles">mission statement</a>. I believe their podcast, <a href="https://oxide-and-friends.transistor.fm/">Oxide and Friends</a>, will have a bigger impact on computing than their rack scale computer.</p>
<blockquote class="blockquote">
<p><strong>Kramer:</strong> Do you ever yearn?<br>
<strong>George:</strong> Yearn? Do I yearn?<br>
<strong>Kramer:</strong> I yearn.<br>
<strong>George:</strong> You yearn.<br>
<strong>Kramer:</strong> Oh, yes. Yes, I yearn. Often, I… I sit… and yearn. Have you yearned?</p>
</blockquote>
<p>Like Kramer, I yearn.</p>
<p>I consider myself a young technologist. I’ve been programming professionally for 1.5 years, recreationally for 4 years. I made the switch from finance into tech July 2021, well after everything had gone remote. Ever since, I felt something was missing.</p>
<p>I yearned for the lunchtime chats, spontaneous whiteboard sessions, after work drinks, and <a href="https://oxide-and-friends.transistor.fm/episodes/rto-or-gfto">office games</a>. The Oxide and Friends podcast has helped fill this gap, recreating these conversations I felt I was missing. A unique format where the podcast is live and listeners can participate in chat.</p>
<p>The topics span <a href="https://oxide-and-friends.transistor.fm/episodes/rebooting-a-datacenter-a-decade-later">production war stories</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/hiring-processes-with-gergely-orosz">hiring processes</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/cultural-idiosyncrasies">culture</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/discovering-the-xz-backdoor-with-andres-freund">security incidents</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/a-baseball-startup-with-paul-freedman-and-bryan-carmel">baseball</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/a-half-century-of-silicon-valley-with-randy-shoup/transcript">silicon valley lore</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/heterogeneous-computing-with-raja-koduri">heterogeneous computing</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/helios">operating systems</a>, <a href="https://oxide-and-friends.transistor.fm/episodes/crates-we-love">rust</a> and much much more.</p>
<p>The podcast has given me a new found interest in computing history, a greater appreciation for hardware and deepened my love for technology. Inspiring other technologists, that is how you change computing forever.</p>
<p>Not everyone can buy an Oxide computer but they can listen to Oxide and Friends.</p>
<p>Thank you to all those involved in making the Oxide and Friends podcast.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/oxide-and-friends/</guid>
  <pubDate>Sun, 24 Aug 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>PyPack Trends Data Is Now Public</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/pypacktrends-goes-public/</link>
  <description><![CDATA[ 




<hr>
<p>I understand many people just want access to the underlying data and not my beautiful chart. That’s okay, I understand. I’ve added a new subdomain <code>data.pypacktrends.com</code> for just this reason.</p>
<p>Now, the official PyPI download data is already publicly available in BigQuery thanks to the <a href="https://packaging.python.org/en/latest/guides/analyzing-pypi-package-downloads/#public-dataset">Linehaul project</a>. The catch is you still need a BigQuery account and, if you’re not careful, you can end up with a <a href="https://tylerhillery.com/blog/cost-effective-bq/">surprise bill</a>.</p>
<p>My export is aggregated to weekly downloads. It’s less granular than Linehaul, but it’s free and no sign up required.</p>
<p>Here is an example with DuckDB:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">set</span> variable list_of_files <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb1-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb1-3">    array_agg(url) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> urls </span>
<span id="cb1-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb1-5">    read_parquet(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://data.pypacktrends.com/pypi-weekly-downloads/manifest.parquet'</span>)</span>
<span id="cb1-6">);</span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb1-9">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> </span>
<span id="cb1-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb1-11">  read_parquet(getvariable(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'list_of_files'</span>), filename <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">True</span>);</span></code></pre></div></div>
<p>I would have loved to allow for file globbing patterns with DuckDB but because I am using <a href="https://developers.cloudflare.com/r2/buckets/public-buckets/">R2 Public Buckets</a> with a custom domain, file globbing doesn’t work like it does with the S3 API.</p>
<blockquote class="blockquote">
<p>I’ve opted for this approach vs.&nbsp;adding a data API, since with static files I don’t have to worry about bots overwhelming my precious $5 VPS.</p>
</blockquote>
<p>Instead I provide a <code>manifest.parquet</code> file. This file has two columns <code>week</code> and <code>url</code>. You can use this file to construct an array of parquet files to fetch. If you only want certain weeks you can add a filter:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">set</span> variable list_of_files <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb2-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> </span>
<span id="cb2-3">    array_agg(url) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> urls </span>
<span id="cb2-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> </span>
<span id="cb2-5">    read_parquet(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://data.pypacktrends.com/pypi-weekly-downloads/manifest.parquet'</span>)</span>
<span id="cb2-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span></span>
<span id="cb2-7">    week <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'2025-08-11'</span></span>
<span id="cb2-8">);</span></code></pre></div></div>
<p>The dataset updates automatically every Monday at 10:00am UTC via a <a href="https://github.com/TylerHillery/pypacktrends/actions/workflows/weekly-pipeline.yml">GitHub Action</a>.</p>
<p>Here is what the schema of the parquet files look like:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 37%">
<col style="width: 62%">
</colgroup>
<thead>
<tr class="header">
<th>Column</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>package_name</code></td>
<td>Name of the PyPI package</td>
</tr>
<tr class="even">
<td><code>package_downloaded_week</code></td>
<td>Week of the downloads (Monday date)</td>
</tr>
<tr class="odd">
<td><code>downloads</code></td>
<td>Number of downloads for that package during the week</td>
</tr>
<tr class="even">
<td><code>cumulative_downloads</code></td>
<td>Running total downloads up to and including this week</td>
</tr>
<tr class="odd">
<td><code>first_distribution_week</code></td>
<td>First week the package appeared on PyPI</td>
</tr>
<tr class="even">
<td><code>weeks_since_first_distribution</code></td>
<td>Number of weeks since the package’s first appearance</td>
</tr>
<tr class="odd">
<td><code>published_at</code></td>
<td>Timestamp of the package’s first release (UTC)</td>
</tr>
</tbody>
</table>
<p>If you want more documentation on how this dataset is generated checkout <a href="https://dbtdocs.pypacktrends.com/#!/model/model.pypacktrends.pypi_package_downloads_weekly_metrics">dbtdocs.pypacktrends.com</a>.</p>
<p>I hope you find the data useful!</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/pypacktrends-goes-public/</guid>
  <pubDate>Tue, 19 Aug 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Internet Zero: How I Consume The Internet</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/how-i-consume-the-internet/</link>
  <description><![CDATA[ 




<hr>
<p>Inbox zero is a methodology of email management with the goal of having zero emails in your inbox. For me it’s simple, I treat my inbox like a todo list. If an email comes in and requires an action either I do it or leave it in my inbox until I do. If no action is required I either delete it or move it to a folder if it’s something I might want to reference later.</p>
<p>I do that exact same thing for consuming the internet, which for the sake of this blog post I am deeming “Internet Zero.”</p>
<p>But the internet doesn’t have an inbox… or does it? Anything you’re subscribed to is your inbox. RSS Feeds, Podcasts, YouTube Channels, Newsletters etc. When something new is posted that piece of content is now in your inbox.</p>
<p>When something is posted in my internet inbox it’s time for me to decide, is this something I want to consume or not? If so I file it away to a “consume it later” folder. Most of the time I don’t consume new content as I discover it but rather when I have dedicated time to do so. If it’s not something I want to consume I delete it. If I find I have been deleting a lot of content from a particular source I unfollow.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>I used to be a big Pocket user but with <a href="https://getpocket.com/farewell">Pocket shutting down</a> I have actually switched to <a href="https://readwise.io/read">Readwise Reader</a> which has been a game changer for me.</p>
<p>Reader has two main concepts, Feeds and Library. Feeds is where all the new content I subscribe to lands first. It’s here I decided to move it to my library as “Later” or delete it. After I consume the content I move it to archived.</p>
<p>I now have one app to manage all my subscriptions whereas before I would go to Spotify to check if new podcasts were posted and then move it to a dedicated “Listen Later” playlist and repeat for all other apps.</p>
</div>
</div>
<p>What about discovery? The problem with only consuming content I subscribe to is I am not exposing myself to content outside of that circle.</p>
<p>Personally I use X, Discord groups, Bluesky and Hackernews as discovery mechanisms. Hackernews is nice because I mainly limit myself to the front page. Discord groups are nice as well because they don’t expose you to an endless feed.</p>
<p>On the other hand, X &amp; Bluesky I use the “For You” feeds which are unbounded. Refresh on and more content appears. It’s endless content like this that can lead to doom scrolling where you find yourself wondering why you have been consuming 3 hours of GCP &amp; Cloudflare outage memes. This is why I have time limits on these sources because there is no real “end” to them.</p>
<p>I stay diligent with the posts I interact with and people I follow so I don’t upset the algo. When I find content I want to consume through these discovery sources they get saved straight to my later library, bypassing my inbox.</p>
<p>That’s the gist. When I have spare time now, instead of heading straight to discovery sources, I go to my later library first or check my internet inbox for new content. I created a <a href="https://tylerhillery.com/lists">lists</a> page where you can check out some of my personal favorites and what I’m currently following.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/how-i-consume-the-internet/</guid>
  <pubDate>Sat, 14 Jun 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>AI Amplifies</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/ai-amplifies/</link>
  <description><![CDATA[ 




<hr>
<p>Much of the hype about AI tools for programming often comes from two ends of a spectrum, those who don’t know programming and those who already have deep expertise.</p>
<p>People who don’t know how to program are blown away because they can accomplish something that was unfeasible to them before.</p>
<p>The experts, on the other hand, can quickly discern whether the output is good or bad. AI removes much of the programming toil so they can focus on the bigger picture.</p>
<p>Couple of quotes that really stuck with me.</p>
<blockquote class="blockquote">
<p><strong>Simon Willison</strong><br>
<em>“LLMs amplify existing expertise”</em><br>
<a href="https://simonwillison.net/2025/Mar/11/using-llms-for-code/#llms-amplify-existing-expertise">Source</a></p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Charlie Marsh</strong><br>
<em>“These tools are a magnifier. But if I were using them without my existing programming experience, it’s so obvious to me that I’d be generating mountains of garbage. And I probably wouldn’t even see it.”</em><br>
<a href="https://x.com/charliermarsh/status/1911119754573591004">Source</a></p>
</blockquote>
<blockquote class="blockquote">
<p><strong>Ankur Goyal</strong><br>
<em>“AI seems to multiply the quality of code that someone would write without AI.</em></p>
<p><em>Bad programmer </em> AI = Lots of bad code*</p>
<p><em>Medium programmer </em> AI = Lots of medium code*</p>
<p><em>Great programmer </em> AI = Lots of great code”*<br>
<a href="https://x.com/ankrgyl/status/1903996985713270931">Source</a></p>
</blockquote>
<p>What if you’re not already great but have aspirations to be great?</p>
<p>Or the better question is, can AI help you become great?</p>
<p>I think so, as long as you <strong>ruthlessly</strong> question it. If you use AI to truly understand.</p>
<p>I am not talking about the hand waving, you get the gist, surface level understanding. You’ll know if you truly understand something if you don’t need AI.</p>
<p>You’re not going to become an expert from vibe coding. Vibe coding is the exact opposite of this. Vibe coding is all about forgetting the code even exists.</p>
<p>Some may not have the goal of becoming a great programmer, then by all means, give into the vibes.</p>
<p>Some may argue AI will become so advanced knowing how to program will become meaningless.</p>
<p>Even so, if you had two people, both can use AI, but one knows nothing about programming and the other is an expert in programming, who do you think will do better?</p>
<p>If everyone is going to access to these AI tools in the future, how will you stand out?</p>
<p>I know how I am. By being the one who truly understands.</p>



 ]]></description>
  <guid>https://www.tylerhillery.com/blog/ai-amplifies/</guid>
  <pubDate>Sun, 13 Apr 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries Web Development</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-web-dev/</link>
  <description><![CDATA[ 




<hr>
<section id="overview" class="level2">
<h2 class="anchored" data-anchor-id="overview">Overview</h2>
<p>As a learning exercise to explore web development, I built <a href="https://pypacktrends.com">PyPack Trends</a>, a web app to compare python package downloads inspired by <a href="https://npmtrends.com">npm trends</a>. Venturing into a new domain can be daunting and I wanted to share my experience.</p>
<p>Before starting any project, I need to understand why. Why am I, as a data engineer, taking the time to learn web development, a domain that does not overlap much with data engineering?</p>
<p>While I work with REST APIs for data extraction, web technologies like HTML, CSS, JavaScript, and web servers aren’t part of my day to day work. Though, as Vicki points out, maybe I’ve been underestimating their importance:</p>
<p></p><div id="tweet-40622"></div><script>tweet={"url":"https:\/\/twitter.com\/vboykis\/status\/1727058177689370907","author_name":"vicki","author_url":"https:\/\/twitter.com\/vboykis","html":"\u003Cblockquote class=\"twitter-tweet\" align=\"center\"\u003E\u003Cp lang=\"en\" dir=\"ltr\"\u003EExtremely consistently underrated skill that I use in ml eng every single day: web dev\u003C\/p\u003E&mdash; vicki (@vboykis) \u003Ca href=\"https:\/\/twitter.com\/vboykis\/status\/1727058177689370907?ref_src=twsrc%5Etfw\"\u003ENovember 21, 2023\u003C\/a\u003E\u003C\/blockquote\u003E\n\u003Cscript async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"\u003E\u003C\/script\u003E\n\n","width":550,"height":null,"type":"rich","cache_age":"3153600000","provider_name":"Twitter","provider_url":"https:\/\/twitter.com","version":"1.0"};document.getElementById("tweet-40622").innerHTML = tweet["html"];</script><p></p>
<p>My drive to learn about the web stems from curiosity and my fundamental belief the web is one of the most essential pieces of tech. It’s the de facto way to share your software with the world.</p>
<p>Even if I don’t do web development for my work, I can do my banking, shopping, coding, etc. through the web. Heck, you can drive a mini jeep around someone’s <a href="https://bruno-simon.com/">personal portfolio</a> on the web. It’s the ultimate medium.</p>
<p>Something this fundamental to my life, yet I didn’t understand how it worked. This bothered me like a loose thread on a piece of clothing. I had to pull at it.</p>
<p>Starting with ‘why’ is crucial because inevitably, self-doubt creeps in, “Why are you even doing this? You’ll never need to know this.” That’s when you need to remember your why. I hit these moments while debugging my <a href="https://bsky.app/profile/tylerhillery.com/post/3lb3g2sxrw224">cloud init script</a> and setting up <a href="https://bsky.app/profile/tylerhillery.com/post/3lb3bojrckk2m">Google Cloud OIDC</a>.</p>
<p>I wanted to build more than just a web app, I wanted a <em>“production grade”</em> application. The often overlooked aspects like testing, CI/CD, observability, monitoring, analytics, and logging were crucial to me. Simply throwing together some HTML, CSS, and JavaScript wasn’t enough. I wanted the full experience of developing and maintaining a real world application.</p>
<p>With that said, I imposed some self constraints as it’s important not to boil the ocean when learning a new domain. If you thought the <a href="https://mattturck.com/mad2024/">Machine Learning, AI, &amp; Data landscape</a> image was overwhelming I don’t even want to know what the web dev landscape would look like.</p>
<p>Their frameworks even have frameworks. It’s a recurring joke that a new UI library is launched every week. I already had ambitious goals for this web app, and I didn’t want to spend my <a href="https://htmx.org/essays/complexity-budget/">complexity budget</a> on learning a whole new language and build tooling. That can come later, as we all have to start somewhere.</p>
<p>I also didn’t want to use a framework such as <a href="https://github.com/streamlit">Streamlit</a>, which I had used before and enjoyed. Streamlit abstracts away too many of the layers of the web I am looking to learn. Instead, I used <a href="https://fastapi.tiangolo.com/">FastAPI</a> as my web framework, <a href="https://picocss.com/">pico css</a> for styling, <a href="https://htmx.org">htmx</a> for interactivity and <a href="https://caddyserver.com/">caddy</a> as my webserver. This is continuously deployed with zero downtime to a VPS running via docker compose.</p>
</section>
<section id="the-web" class="level2">
<h2 class="anchored" data-anchor-id="the-web">The Web</h2>
<p>As a data engineer, I’m used to thinking about data pipelines and transformations. However, the web introduces a different kind of pipeline. One that starts with a URL being typed into a browser and ends with a rendered page on your screen.</p>
<p>Understanding this pipeline gave me a deeper appreciation for what happens whenever I visit a web page. When you type a URL into your browser, a series of steps occur to transform that URL into a rendered web page:</p>
<ol type="1">
<li><strong>DNS Resolution</strong>: The browser contacts a DNS server to resolve the domain name into an IP address.</li>
<li><strong>TCP Connection</strong>: The browser establishes a TCP connection with the server at the resolved IP address.</li>
<li><strong>TLS Handshake</strong>: If using HTTPS, the browser and server perform a TLS handshake to establish a secure connection.</li>
<li><strong>HTTP Request</strong>: The browser sends an HTTP request to the server, asking for the content at the specified URL.</li>
<li><strong>Server Processing</strong>: The server processes the request, which may involve querying a database, running application logic, and generating HTML.</li>
<li><strong>HTTP Response</strong>: The server returns an HTTP response containing the requested content.</li>
<li><strong>Rendering</strong>: The browser parses the HTML, CSS, and JavaScript, and renders the web page on the screen.</li>
</ol>
<p>It’s crazy to think about the number of steps to load a simple web page. For Python web apps, there are even more layers involved.</p>
<p>Python has two interface standards: WSGI (Web Server Gateway Interface) and ASGI (Asynchronous Server Gateway Interface). Servers like Gunicorn (WSGI) and Uvicorn (ASGI) implement these interfaces to communicate between web servers and Python web applications like FastAPI. These servers handle translating HTTP requests into something Python can understand.</p>
<p>On top of these application servers, you typically need a web server and reverse proxy like Nginx or Caddy. These serve static files efficiently and route HTTP requests to your application servers. I chose Caddy because of its ease of use and automatic HTTPS.</p>
<p>I found this definition from Real Python to provide a great mental model of the various layers of a Python web app:</p>
<blockquote class="blockquote">
<p>Django is a web framework. It lets you build the core web application that powers the actual content on the site. It handles HTML rendering, authentication, administration, and backend logic.</p>
<p>Gunicorn is an application server. It translates HTTP requests into something Python can understand. Gunicorn implements the Web Server Gateway Interface (WSGI), which is a standard interface between web server software and web applications.</p>
<p>Nginx is a web server. It’s the public handler, more formally called the reverse proxy, for incoming requests and scales to thousands of simultaneous connections. <sup>1</sup></p>
</blockquote>
</section>
<section id="getting-started" class="level2">
<h2 class="anchored" data-anchor-id="getting-started">Getting Started</h2>
<p>With clear requirements, a Why, I was ready. So I crack open my terminal create a new directory and open my editor… now what? Where do I even begin? Well just like Picasso said <em>“Good artists copy. Great artists”</em> that’s what I did.</p>
<p>While searching for similar projects I found the <a href="https://github.com/fastapi/full-stack-fastapi-template">full-stack-fastapi-template</a>. I didn’t end up using this exact template but it was another reference implementation I used to get started.</p>
<p>One thing I really liked about the template was the repository structure. It’s a monorepo where each sub directory represents an individual project that could be theoretically separated into its own repository. I liked thinking of each sub directory as its own service.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> tree <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> 1</span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">.</span></span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> LICENSE</span>
<span id="cb1-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> README.md</span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> alloy</span>
<span id="cb1-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> backend</span>
<span id="cb1-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> caddy</span>
<span id="cb1-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> data</span>
<span id="cb1-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> dbt</span>
<span id="cb1-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> deployment.md</span>
<span id="cb1-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> development.md</span>
<span id="cb1-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> docker-compose.override.yml</span>
<span id="cb1-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> docker-compose.yml</span>
<span id="cb1-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> infra</span>
<span id="cb1-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> litestream</span>
<span id="cb1-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├──</span> logs</span>
<span id="cb1-17"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└──</span> scripts</span></code></pre></div></div>
<p>The first thing I did when starting the project was develop the <a href="https://www.tylerhillery.com/blog/cicd-for-your-vps/">CI/CD Pipeline</a>.</p>
<p>This might sound counterintuitive given my goal of learning web development, but it provided a solid foundation and forced me to start with something. This was the initial version of the web app when I initially launched it:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastapi <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> FastAPI</span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastapi.responses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> HTMLResponse</span>
<span id="cb2-3"></span>
<span id="cb2-4">app <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FastAPI()</span>
<span id="cb2-5"></span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.get</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/"</span>, response_class<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>HTMLResponse)</span>
<span id="cb2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> root() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> HTMLResponse:</span>
<span id="cb2-9">    html_content <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    &lt;html&gt;</span></span>
<span id="cb2-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        &lt;head&gt;</span></span>
<span id="cb2-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;title&gt;PyPack Trends&lt;/title&gt;</span></span>
<span id="cb2-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        &lt;/head&gt;</span></span>
<span id="cb2-14"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        &lt;body&gt;</span></span>
<span id="cb2-15"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;h3&gt;PyPack Trends 🐍 coming soon...&lt;/h3&gt;</span></span>
<span id="cb2-16"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        &lt;/body&gt;</span></span>
<span id="cb2-17"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    &lt;/html&gt;</span></span>
<span id="cb2-18"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> html_content</span>
<span id="cb2-20"></span>
<span id="cb2-21"></span>
<span id="cb2-22"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@app.get</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/health-check/"</span>)</span>
<span id="cb2-23"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">async</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> health_check() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb2-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span></code></pre></div></div>
<p>The upfront investment in the CI/CD pipeline allowed me to quickly iterate and deploy changes, ensuring I could focus on learning without worrying about the deployment process.</p>
</section>
<section id="interactivity-with-htmx" class="level2">
<h2 class="anchored" data-anchor-id="interactivity-with-htmx">Interactivity with htmx</h2>
<p>The final web app is actually just one HTML file. I used <a href="https://htmx.org/">htmx</a> to handle the interactive parts of the app, such as active search, adding packages to the list, retrieving the charts, and so on.</p>
<p>Htmx allowed me to define specific “triggers” using the <code>hx-trigger</code> attribute, which initiates an AJAX request. AJAX (Asynchronous JavaScript and XML) allows web pages to be updated asynchronously by exchanging small amounts of data with the server behind the scenes. This means that parts of a web page can be updated without reloading the entire page<sup>2</sup>.</p>
<p>By specifying the type of request with <code>hx-get</code>, <code>hx-post</code> or <code>hx-delete</code> attributes in the HTML tag, the request is sent to the server and handled by the corresponding FastAPI route. In the FastAPI route, I perform data validation and logic to generate the response, eventually returning HTML fragments back to the client. Htmx then swaps the HTML content based on the <code>hx-swap</code> and <code>hx-target</code> attributes.</p>
<p>The <a href="https://htmx.org/examples/">htmx examples</a> proved invaluable in understanding how to implement interactivity in my web app. My favorite example is <a href="https://htmx.org/examples/active-search/">active search</a> which I used on my site to show python packages as you type in the search bar.</p>
<p>Working directly with HTML attributes in htmx gave me hands on experience with web fundamentals. True to its “HTML++” pitch, it enhanced HTML while keeping me close to the underlying technology, improving my overall learning process.</p>
</section>
<section id="observability" class="level2">
<h2 class="anchored" data-anchor-id="observability">Observability</h2>
<p>I was prepared to have this detailed section on setting up observability for my app but it turned out to be very underwhelming, which is a good thing!</p>
<p>Setting up <a href="https://grafana.com/">Grafana</a> monitoring was straightforward. Following their Docker integration <a href="https://grafana.com/docs/alloy/latest/set-up/install/docker/">docs</a>, I added Grafana’s Alloy agent as a service in my docker compose file to forward logs and metrics to Grafana Cloud.</p>
<p>For monitoring my SQLite backups, I found a pre-built <a href="https://litestream.io/">Litestream</a> dashboard in a <a href="https://github.com/benbjohnson/litestream/issues/86">GitHub issue</a>. Setting up Litestream in Docker was simple thanks to their <a href="https://litestream.io/guides/docker/">documentation</a>, though I did have to peek at the source code to see how to expose the metrics, which turned out to be a simple line in the <code>litestream.yml</code> file <code>addr: "0.0.0.0:9090"</code></p>
<div class="callout callout-style-simple callout-caution no-icon callout-titled" title="Grafana Dashboards">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Caution</span>Grafana Dashboards
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-grafana-linux.svg" class="img-fluid">
<p style="text-align: center;">
<b>Grafana Linux Integration Overview</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-grafana-docker.svg" class="img-fluid">
<p style="text-align: center;">
<b>Grafana Docker Integration Overview</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-grafana-docker-logs.svg" class="img-fluid">
<p style="text-align: center;">
<b>Grafana Docker Integration Logs</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-grafana-litestream.svg" class="img-fluid">
<p style="text-align: center;">
<b>Grafana Litestream Overview</b>
</p>
</div>
</div>
</div>
<p>Setting up <a href="https://sentry.io/welcome/">Sentry</a> was as simple as adding this code in my <code>main.py</code> file for my FastAPI app.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> settings.SENTRY_DSN <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> settings.ENVIRONMENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dev"</span>:</span>
<span id="cb3-2">    logger.info(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Initializing Sentry SDK"</span>)</span>
<span id="cb3-3">    sentry_sdk.init(</span>
<span id="cb3-4">        dsn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(settings.SENTRY_DSN),</span>
<span id="cb3-5">        enable_tracing<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb3-6">        traces_sample_rate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>,</span>
<span id="cb3-7">        _experiments<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb3-8">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"continuous_profiling_auto_start"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb3-9">        },</span>
<span id="cb3-10">    )</span></code></pre></div></div>
<p>And this script HTML tag for session replays</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource html number-lines code-with-copy"><code class="sourceCode html"><span id="cb4-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://js.sentry-cdn.com/2f6693a1a57f2f806caa2d34fe9cbd7e.min.js"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> crossorigin</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"anonymous"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<p>I initially underestimated Sentry’s capabilities, thinking it was primarily for error alerting. However, it also offers valuable performance insights, such as identifying the slowest endpoints and DB queries.</p>
<p>The error alerting was helpful as it helped me identify a couple of issues where I was returning a 500 level status code when it should have been a 400 level.</p>
<div class="callout callout-style-simple callout-note no-icon callout-titled" title="Sentry Dashboards">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Sentry Dashboards
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-sentry-project.svg" class="img-fluid">
<p style="text-align: center;">
<b>Sentry Project Overview</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-sentry-perf.svg" class="img-fluid">
<p style="text-align: center;">
<b>Sentry Performance Dashboard</b>
</p>
</div>
</div>
</div>
<p>Setting up PostHog for web analytics was also done by adding an HTML script tag:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource html number-lines code-with-copy"><code class="sourceCode html"><span id="cb5-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb5-2">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e) { <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> o<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">__SV</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">window</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">posthog</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">_i</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">init</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> a) { <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">g</span>(t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e) { <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> o<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> (t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t[o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> t[e] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () { t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>([e]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">concat</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Array</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prototype</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">slice</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">call</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">arguments</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>))) } } (p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">createElement</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"script"</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text/javascript"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">crossOrigin</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"anonymous"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">async</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">src</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">api_host</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replace</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".i.posthog.com"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-assets.i.posthog.com"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/static/array.js"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> (r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getElementsByTagName</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"script"</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">parentNode</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">insertBefore</span>(p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> r)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> u <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">void</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!==</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> u <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> e[a] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"posthog"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">people</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">people</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">toString</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (t) { <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"posthog"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"posthog"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!==</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> (e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> a)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> (e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" (stub)"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">people</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">toString</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">toString</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".people (stub)"</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> o<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>)<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">g</span>(u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> o[n])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">_i</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>([i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> a]) }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">__SV</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) }(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">window</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">posthog</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> [])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-3">  posthog<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">init</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'phc_p0ITJzZ8QM1sBKYur3ugA5kqgemya2DMEpccVw5KmMO'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> {</span>
<span id="cb5-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">api_host</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://us.i.posthog.com'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-5">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">person_profiles</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'identified_only'</span></span>
<span id="cb5-6">  })</span>
<span id="cb5-7"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<div class="callout callout-style-simple callout-warning no-icon callout-titled" title="PostHog Dashboards">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Warning</span>PostHog Dashboards
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-posthog-homepage.svg" class="img-fluid">
<p style="text-align: center;">
<b>PostHog Homepage</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-posthog-web-analytics.svg" class="img-fluid">
<p style="text-align: center;">
<b>PostHog Web Analytics</b>
</p>
<img src="https://www.tylerhillery.com/assets/images/pypacktrends-posthog-session-replay.svg" class="img-fluid">
<p style="text-align: center;">
<b>PostHog Session Replay</b>
</p>
</div>
</div>
</div>
</section>
<section id="fun-challenges-i-faced" class="level2">
<h2 class="anchored" data-anchor-id="fun-challenges-i-faced">Fun Challenges I Faced</h2>
<p>This project exposed me to interesting challenges that would have been hard to learn through a course or book.</p>
<section id="oom" class="level3">
<h3 class="anchored" data-anchor-id="oom">OOM</h3>
<p>My first hurdle was exit code 125 in my GitHub Action, an out of memory (OOM) error occurring while syncing BigQuery data to SQLite on my VPS. This became an opportunity to dive into Python memory profiling.</p>
<p>I opted to use <a href="https://github.com/bloomberg/memray/tree/main">memray</a>, developed by the fantastic folks at Bloomberg. Uv made running memray as simple as:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">uv</span> run <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--with</span> memray memray run app/sync.py packages</span></code></pre></div></div>
<p>This produces a helpful message to generate a flame graph.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">You</span> can now generate reports from the stored allocation records.</span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Some</span> example commands to generate reports:</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/Users/tyler/.cache/uv/archive-v0/3-XBNEwI_aeReaU130YLC/bin/python</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> memray flamegraph app/memray-sync.py.98012.bin</span></code></pre></div></div>
<p>Flamegraphs initially confused me because I kept treating the x-axis as time, but left-to-right ordering has no special meaning. While the memray <a href="https://bloomberg.github.io/memray/flamegraph.html">docs</a> and Brendan Greg’s excellent talk <a href="https://www.youtube.com/watch?v=VMpTU15rIZY">Visualizing Performance - The Developers’ Guide to Flame Graphs</a> helped explain the concepts, what really clicked was profiling my own code. Seeing my functions in the flame patterns made the visualization immediately more intuitive.</p>
<p>The profiler revealed the peak memory usage. My first attempt at optimization was to reduce the batch size from 50,000 to 5,000 rows, which had no effect. This seemed odd. Turned out, the issue wasn’t the batch size but how I was iterating over the BigQuery results.</p>
<p>My original code attempted to use <code>islice</code> to iterate through the BigQuery results without loading them all into memory at once:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1">BATCH_SIZE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50_000</span></span>
<span id="cb8-2"></span>
<span id="cb8-3">job_config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bigquery.QueryJobConfig(</span>
<span id="cb8-4">    labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb8-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"application"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pypacktrends"</span>,</span>
<span id="cb8-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"component"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sync"</span>,</span>
<span id="cb8-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"packages"</span>,</span>
<span id="cb8-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"environment"</span>: settings.ENVIRONMENT,</span>
<span id="cb8-9">    }</span>
<span id="cb8-10">)</span>
<span id="cb8-11">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.query(select_query, job_config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>job_config).result()</span>
<span id="cb8-12">total_rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rows.total_rows</span>
<span id="cb8-13">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(rows)</span>
<span id="cb8-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> write_engine.begin() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> conn:</span>
<span id="cb8-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> batch <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(islice(rows, BATCH_SIZE)):</span>
<span id="cb8-16">        packages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(row.items()) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> batch]</span>
<span id="cb8-17">        conn.execute(upsert_sql, packages)</span></code></pre></div></div>
<p>The issue? BigQuery was loading 50,000 rows regardless of the batch size setting. The solution was to use BigQuery’s native <code>page_size</code> parameter to properly stream the results:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb9-1">BATCH_SIZE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5000</span></span>
<span id="cb9-2"></span>
<span id="cb9-3">job_config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> bigquery.QueryJobConfig(</span>
<span id="cb9-4">    labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb9-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"application"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pypacktrends"</span>,</span>
<span id="cb9-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"component"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sync"</span>,</span>
<span id="cb9-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"packages"</span>,</span>
<span id="cb9-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"environment"</span>: settings.ENVIRONMENT,</span>
<span id="cb9-9">    }</span>
<span id="cb9-10">)</span>
<span id="cb9-11">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.query(select_query, job_config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>job_config).result(</span>
<span id="cb9-12">    page_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BATCH_SIZE</span>
<span id="cb9-13">)</span>
<span id="cb9-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> write_engine.begin() <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> conn:</span>
<span id="cb9-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> page <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows.pages:</span>
<span id="cb9-16">        packages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(row.items()) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> page]</span>
<span id="cb9-17">        conn.execute(upsert_sql, packages)</span></code></pre></div></div>
<p>The other thing that stood out to me in the Flamegraph was seeing memory allocations from python packages that I wasn’t using in this file. I learned when you use <code>from module import function</code> python still loads the entire module. I saw this in my memory flame graph. Moving functions with heavy deps to a separate file deleted a whole “flame” of memory allocations.</p>
<p><img src="https://www.tylerhillery.com/assets/images/memray-flamegraph.svg" class="img-fluid"></p>
<p>With all these improvements implemented I was able to reduce my peak memory usage from 400MiB to 100MiB a 75% reduction! This resolved the OOM error I was facing in my GitHub Action.</p>
</section>
<section id="no-more-disk-and-no-more-db" class="level3">
<h3 class="anchored" data-anchor-id="no-more-disk-and-no-more-db">No more disk and No more db</h3>
<p>The other challenge I faced was running out of disk space. I explored ways to reduce disk space such as removing indexes from SQLite that were only used during the weekly sync.</p>
<p>This reclaimed ~5GB of disk space but it still wasn’t enough. I gave in and upgraded my droplet from 1GB Memory and 25GB Disk space to the next size up which is 2GB Memory and 50GB Disk Space. No more $5 VPS 😢.</p>
<div class="callout callout-style-simple callout-tip">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p><strong>Learning Through Constraints</strong>: Starting with a minimal VPS forced me to optimize code and understand memory usage, I highly recommended imposing these constraints before throwing resources at the problem.</p>
</div>
</div>
</div>
<p>Upgrading my VPS required me to redeploy it. This meant adding a database restoration process to my cloud-init script. I don’t have a staging environment to test this so I just went for it. Everything seemed to work at first until I realized my database file was only 200MiB when it used to be 12GiB…</p>
<p>This was very concerning as it took me over 14 hours to sync the entire dataset from BigQuery to SQLite. Fortunately, Litestream maintains multiple backup generations, specifying an older generation in the restore command recovered the full database. While the root cause remains unclear, Litestream’s multiple generations provide a safety net for future restores.</p>
<p>Step one to becoming a senior engineer: drop the prod database. Check.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>This has been, by far, the most rewarding personal project I’ve built. After acquiring <a href="https://pypacktrends.com">pypacktrends.com</a> in late October 2024, I set out to complete the project by year’s end, and the journey has been incredibly educational.</p>
<p>I gained hands on experience across the entire software development lifecycle by developing this web application. I was challenged to think holistically about software development beyond just writing code.</p>
<p>This project has given me a solid foundation in full-stack development that I’m excited to build upon in future work.</p>
<p>Stay tuned for what I try next.</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><a href="https://realpython.com/django-nginx-gunicorn/?utm_source=pocket_shared#incorporating-nginx">Real Python: Django, Nginx, and Gunicorn</a>↩︎</p></li>
<li id="fn2"><p><a href="https://www.w3schools.com/whatis/whatis_ajax.asp">AJAX</a>↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>Web Development</category>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-web-dev/</guid>
  <pubDate>Thu, 26 Dec 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>How PyPack Trends Cost Effectively Queries 440TB of PyPI Data</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/cost-effective-bq/</link>
  <description><![CDATA[ 




<hr>
<p>There’s nothing more exhilarating than knowing one SQL query could end up costing you $2,750. But if you don’t like living on the edge, here are some techniques to help reduce your query costs.</p>
<p>BigQuery’s On-demand pricing model costs $6.25 per TiB, with the first TiB per month being free. I have been building <a href="https://pypacktrends.com">PyPack Trends</a>, a web app to compare Python package downloads inspired by <a href="https://npmtrends.com">npm trends</a>. This app served as a learning exercise to explore web development.</p>
<p>A core part of this app is being able to cost-effectively serve the PyPI package downloads dataset. The dataset is made available on BigQuery for free, thanks to the <a href="https://packaging.python.org/en/latest/guides/analyzing-pypi-package-downloads/#public-dataset">Linehaul project</a>. The downloads dataset alone is 440TB, which comes out to $2,750 if you run a simple <code>select * from bigquery-public-data.pypi.file_downloads</code>.</p>
<p>We can confirm this by either running a <a href="https://cloud.google.com/bigquery/docs/samples/bigquery-query-dry-run">dry run query</a> or if you’re using BigQuery studio, in the upper right-hand corner of the editor, it will display the estimated amount of bytes to be scanned if you run the query.</p>
<p><img src="https://www.tylerhillery.com/assets/images/bq-bytes-scanned.png" alt="bigquery-bytes-scanned"></p>
<p>This is where understanding how the internals of your database can help you write cost-effective and performant queries.</p>
<p>One way to reduce the amount of data scanned is by selecting only the columns you need. BigQuery stores table data in a columnar format. This means when we select only one column, BigQuery will only scan that column’s worth of data. If I changed the query from doing a <code>select * from bigquery-public-data.pypi.file_downloads</code> to <code>select project from bigquery-public-data.pypi.file_downloads</code> this drops the data scanned from 440TB to 13.39TB which is $2,666 less.</p>
<p>Another way to reduce the amount of data scanned is by taking advantage of partition pruning. A partitioned table divides the table into “chunks” called partitions. A standard column to partition on is typically a date column such as <code>order_date</code>, in our case, the PyPI file downloads table is partitioned on the <code>timestamp</code> column representing download time. This query will only scan 463.50 GB of data, <code>select * from bigquery-public-data.pypi.file_downloads where timestamp_trunc(timestamp, day) = timestamp("2024-12-14")</code>.</p>
<p>While partitioning divides the data into smaller segments, clustering defines the table’s sort order. The formal definition from the BigQuery <a href="https://cloud.google.com/bigquery/docs/clustered-tables">docs</a></p>
<blockquote class="blockquote">
<p>A clustered column is a user-defined table property that sorts storage blocks based on the values in the clustered columns.</p>
</blockquote>
<p>Like partition pruning, BigQuery will also prune these blocks when filtering on this column. Running the query <code>select * from bigquery-public-data.pypi.file_downloads where project = 'duckdb'</code> results in 762.27 GB scanned.</p>
<p>Columns commonly used for clustering are those frequently used in join operations. This image does a great job visualizing table partitioning and clustering:</p>
<div style="font-size: 50%;">
<p><img src="https://www.tylerhillery.com/assets/images/clustering-and-partitioning-tables.png" class="img-fluid"> <a href="https://cloud.google.com/bigquery/docs/clustered-tables"><em>https://cloud.google.com/bigquery/docs/clustered-tables</em></a></p>
</div>
<p>Even with all these techniques implemented, BigQuery is not designed for frequent small-point queries targeting an individual row but rather large aggregate queries running across many rows. The terms to often describe these workloads are OLTP and OLAP.</p>
<p>Further optimization can be done by incrementally pre-aggregating the data and then exporting it to another more optimized database for OLTP workloads.</p>
<p>Daily download counts are too “nosiy” making it look like there are dramatic increases and decreases in daily downloads for a given package. To help smooth out the curve, I opted to pre-aggregate weekly per package.</p>
<p>Incremental processing is essential here because once we calculate one week’s download counts there should be no need to recompute that data again. To calculate the weekly downloads per project takes ~230 GB scanned. Ran 4 times a month would result in 80 GB shy of the free 1 TB per month. Perfect.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span></span>
<span id="cb1-2">    project,</span>
<span id="cb1-3">    date_trunc(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">date</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">timestamp</span>), week (monday)) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_downloaded_week,</span>
<span id="cb1-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>)                                   <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> downloads</span>
<span id="cb1-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span></span>
<span id="cb1-6">    bigquery<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">data</span>.pypi.file_downloads</span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span></span>
<span id="cb1-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">timestamp</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'2024-12-02'</span></span>
<span id="cb1-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">timestamp</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'2024-12-09'</span></span>
<span id="cb1-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">group</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">by</span></span>
<span id="cb1-11">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span></code></pre></div></div>
<p>I prefer to use a tool like <a href="https://github.com/dbt-labs/dbt-core">dbt</a> to manage these queries, as it helps apply software engineering best practices to SQL code. Dbt even has a built-in <a href="https://docs.getdbt.com/docs/build/incremental-models">incremental materialization</a> method, which materializes as a table in your database and only transforms the data you tell dbt to filter for.</p>
<p>A best practice to help minimize the chance of running an expensive query is setting the <code>maximum_bytes_billed</code> in your dbt profile. Here is how I have configured my <code>dev</code> profile.</p>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Caution
</div>
</div>
<div class="callout-body-container callout-body">
<p>I have noticed that the BigQuery estimated bytes scanned can be overstated when running incremental models, so I have set it much higher than I would have liked here.</p>
</div>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource yml number-lines code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">target</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> dev</span></span>
<span id="cb2-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">outputs</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dev</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">type</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> bigquery</span></span>
<span id="cb2-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">method</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> oauth</span></span>
<span id="cb2-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">project</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> pypacktrends-prod</span></span>
<span id="cb2-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dataset</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dbt_{{ env_var('BIGQUERY_USER') }}"</span></span>
<span id="cb2-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">priority</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> batch</span></span>
<span id="cb2-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">threads</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb2-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">timeout_seconds</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span></span>
<span id="cb2-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">maximum_bytes_billed</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300000000000</span></span></code></pre></div></div>
<p>I have also developed a dbt macro called <code>pypi_package_filter</code> which checks the dbt target to see if it should filter for only a subset of packages. For the <code>dev</code> and <code>ci</code> targets I don’t need to be querying the full range of packages.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb3-1">{% macro pypi_package_filter(column_name) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>%}</span>
<span id="cb3-2">    {% <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">set</span> package_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb3-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dask'</span>,</span>
<span id="cb3-4">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'datafusion'</span>,</span>
<span id="cb3-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duckdb'</span>,</span>
<span id="cb3-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'getdaft'</span>,</span>
<span id="cb3-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ibis-framework'</span>,</span>
<span id="cb3-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pandas'</span>,</span>
<span id="cb3-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'polars'</span>,</span>
<span id="cb3-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pyspark'</span></span>
<span id="cb3-11">    ] %}</span>
<span id="cb3-12"></span>
<span id="cb3-13">    {%<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> target.name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prod'</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>%}</span>
<span id="cb3-14">        {{ column_name }} <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'{{ package_list | join("'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'") }}'</span>)</span>
<span id="cb3-15">    {%<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>%}</span>
<span id="cb3-16">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span></span>
<span id="cb3-17">    {%<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> endif <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>%}</span>
<span id="cb3-18"></span>
<span id="cb3-19">{% endmacro %}</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource sql number-lines code-with-copy"><code class="sourceCode sql"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span></span>
<span id="cb4-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">source</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> (</span>
<span id="cb4-3">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> {{ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">source</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pypi'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'file_downloads'</span>) }}</span>
<span id="cb4-4">),</span>
<span id="cb4-5"></span>
<span id="cb4-6">renamed <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> (</span>
<span id="cb4-7">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span></span>
<span id="cb4-8">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">timestamp</span>    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_downloaded_at,</span>
<span id="cb4-9">        country_code <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_country_code,</span>
<span id="cb4-10">        url          <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_url_path,</span>
<span id="cb4-11">        project      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_name,</span>
<span id="cb4-12">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">file</span>         <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_file_details,</span>
<span id="cb4-13">        details      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_details,</span>
<span id="cb4-14">        tls_protocol <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_tls_protocol,</span>
<span id="cb4-15">        tls_cipher   <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> package_download_tls_cipher</span>
<span id="cb4-16">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span></span>
<span id="cb4-17">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">source</span></span>
<span id="cb4-18">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> </span>
<span id="cb4-19">        {{ pypi_package_filter(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'project'</span>) }}</span>
<span id="cb4-20">)</span>
<span id="cb4-21"></span>
<span id="cb4-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">select</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> renamed</span></code></pre></div></div>
<p>Lastly, I use dbt <a href="https://docs.getdbt.com/reference/commands/clone">clone</a> which takes advantage of BigQuery’s <a href="https://cloud.google.com/bigquery/docs/table-clones-intro">table clone</a> feature.</p>
<blockquote class="blockquote">
<p>A table clone is a lightweight, writable copy of another table (called the base table). You are only charged for storage of data in the table clone that differs from the base table, so initially there is no storage cost for a table clone. Other than the billing model for storage, and some additional metadata for the base table, a table clone is similar to a standard table—you can query it, make a copy of it, delete it, and so on.</p>
</blockquote>
<p>This allows me to create a full copy of the expensive weekly downloads model into my own dev dataset at zero cost without having to recreate it from scratch. This feature requires access to the production dbt manifest JSON file, which fully represents your dbt project’s resources.</p>
<p>I run my dbt jobs through GitHub Actions and save the generated manifest file to my VPS ( I even have the dbt docs publicly available at <a href="https://dbtdocs.pypacktrends.com/#!/overview">dbtdocs.pypacktrends.com</a> ). To retrieve the manifest file I rsync the files to my local machine.</p>
<p>After the data is pre-aggregated, I sync the data to an SQLite file on the VPS, essentially using SQLite as a read-only cache. I’m still experimenting with ways to relax SQLite settings to improve query performance, given the heavy read workload with infrequent writes ( once a week). Data reliability is also not a concern here as the source of truth is BigQuery, and I can always resync the data if I have to.</p>
<p>The downside of all this is that I no longer get the thrill when I run my queries. In tech, there are always tradeoffs.</p>



 ]]></description>
  <category>FinOps</category>
  <category>Query Optimization</category>
  <guid>https://www.tylerhillery.com/blog/cost-effective-bq/</guid>
  <pubDate>Sun, 15 Dec 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>CI/CD For Your $5 VPS</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/cicd-for-your-vps/</link>
  <description><![CDATA[ 




<hr>
<p>To learn about web development, I set out to build a production grade web app.</p>
<p>What does “production grade” mean? For me, it means the app includes:</p>
<ul>
<li>Tests</li>
<li>Linting, formatting, and type-checking</li>
<li>Application monitoring</li>
<li>Observability</li>
<li>Logging</li>
<li>Infrastructure as Code</li>
<li>Automated deployment pipeline</li>
<li>Zero downtime deploys</li>
<li>Secrets management</li>
<li>Documentation</li>
<li>Containerization</li>
</ul>
<p>Before building the web app, I started by creating the deployment pipeline. When working on a project, it bothers me if I don’t know how I’ll deploy it. I want to know when the final commit is merged into <code>main</code>, the app will be automatically deployed within minutes, live for the world to see.</p>
<p>One of the first things I set up for a new project is <a href="https://pre-commit.com/">pre-commit</a> and <a href="https://github.com/features/actions">GitHub Actions</a>. GitHub Actions can run workflows triggered by repo activity, like a pull request. Pre-commit is a tool for managing git commit hooks to perform actions before committing.</p>
<p>Pre-commit hooks can be a polarizing topic, I like the tool because it conveniently packages other tools to enforce linting, type checking, formatting etc. on your code. Whether or not these are ran locally, I use the <a href="https://github.com/pre-commit/action">pre-commit/action</a> to enforce them on PRs.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource yml number-lines code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Test</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">on</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">branches</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> main</span></span>
<span id="cb1-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pull_request</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">types</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> opened</span></span>
<span id="cb1-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> synchronize</span></span>
<span id="cb1-11"></span>
<span id="cb1-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jobs</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pre-commit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runs-on</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ubuntu-latest</span></span>
<span id="cb1-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">steps</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> actions/checkout@v4</span></span>
<span id="cb1-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Set up Python</span></span>
<span id="cb1-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> actions/setup-python@v5</span></span>
<span id="cb1-19"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-20"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">python-version-file</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".python-version"</span></span>
<span id="cb1-21"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">uses</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> pre-commit/action@v3.0.1</span></span></code></pre></div></div>
<p>I prefer to enable them locally so I know ahead of time if this action will fail. Most pre-commit hooks will auto fix the errors they detect anyway.</p>
<p>Containerizing the app gives it flexibility on where it can be deployed. With the recent rise in self-hosting, I was drawn to using a plain old VPS. While many PaaS and cloud providers make deploying apps trivial, it’s tough to appreciate the value they add without experiencing solutions without all the bells and whistles. I don’t want to be a pink elephant<sup>1</sup>.</p>
<p>Since I planned to have at least two containers running on this VPS, I needed a way to orchestrate them. Tools like Kubernetes or Docker Swarm felt too heavy for my needs, so Docker Compose felt like the right solution, especially as availability isn’t critical for this app. One nice benefit of Docker Compose is how easy it’s to run locally. Using the same technology for both production and development provides numerous benefits.</p>
<p>I knew I wouldn’t set up my VPS through ClickOps. Instead, I used Pulumi for infrastructure as code and secrets management. Pulumi does a lot for my app, it handles building and publishing the image to ghcr.io, generating SSH keys, provisioning the VPS, setting up DNS records, configuring email routing, and running remote commands. The remote command triggers on any image changes and runs the <a href="https://github.com/TylerHillery/pypacktrends/blob/main/scripts/update_service.sh">update_service.sh</a> script. ( more on that later)</p>
<p>On startup, the VPS runs a <a href="https://github.com/TylerHillery/pypacktrends/blob/main/infra/templates/cloud-init.yml">cloud-init</a> script which configures the VPS to disallow password login, runs <code>apt update</code> <code>apt upgrade</code>, installs docker, installs tailscale, installs uv, clones repo, creates logging directory, starts containers, and configures ufw.</p>
<p>Pulumi is also great because I can use the same programming language for my IaC as I use for the backend. This lets me use additional packages, like jinja2, to turn the cloud-init file into a template, allowing Pulumi to inject configuration values.</p>
<p>On each PR, pulumi preview runs via GitHub Actions and outputs the summary as a PR comment, so I know what changes will occur when the PR is merged. After merging the PR, this triggers another GitHub action to run pulumi up to deploy any changes.</p>
<p>When I first got the <code>update_service.sh</code> script to work, it felt like magic. The script itself is inspired by a great video from Tom Delalande, <a href="https://youtu.be/jFrGhodqC08?si=CCiQYRmts3zmvDdR">The cloud is over-engineered and overpriced</a>. This script is what enables zero-downtime deploys. It first pulls the new image from ghcr.io which makes the old image “dangling”. We can find the image ID of dangling image by filtering for it.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">dangling_image</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> images <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--filter</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dangling=true"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--filter</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"reference=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${CONTAINER_REGISTRY_PREFIX}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${SERVICE_NAME}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--format</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{{.ID}}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
<p>Once we get the old image ID we can get the old container name by running.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">old_container</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> ps <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--filter</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ancestor=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dangling_image</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--format</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{{.Names}}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
<p>Now, we can scale up the service to two containers, but we need to specify to not restart the currently running container. The new container will use the latest image we just pulled.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> compose <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> docker-compose.yml up <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-d</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-deps</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--scale</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$SERVICE_NAME</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>=2 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-recreate</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$SERVICE_NAME</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span></code></pre></div></div>
<p>Once that’s done, we can get the new container name.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">new_container</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> ps <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--filter</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ancestor=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${FULL_IMAGE_NAME}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--format</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{{.Names}}"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grep</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$SERVICE_NAME</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tail</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> 1<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
<p>We need to update our reverse proxy, caddy, to direct traffic to our new container by changing the container name env var.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CONTAINER_NAME</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${SERVICE_NAME}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tr</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'[:lower:]'</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'[:upper:]'</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span>_CONTAINER_NAME</span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> exec <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$caddy_container</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"export </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${CONTAINER_NAME}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$new_container</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> &amp;&amp; caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile"</span></span></code></pre></div></div>
<p>Lastly, we clean up the old container and image.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> container rm <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$old_container</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> rmi <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dangling_image</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span></code></pre></div></div>
<p>Tailscale was added because it provides a more secure and convenient way to handle SSH. It enables the GitHub Action to run remote commands and allows me to SSH into the VPS if needed. I generated the SSH key in Pulumi only as a backup in case I needed to debug the cloud-init script before Tailscale gets installed. Additionally, DigitalOcean requires you to create a password if you don’t assign an SSH key when provisioning the droplet.</p>
<p>So there you have it, CI/CD for your $5 VPS.</p>
<section id="caveats" class="level2">
<h2 class="anchored" data-anchor-id="caveats">Caveats</h2>
<p>I’m still running into a few issues with the current setup. At the moment, <a href="https://github.com/TylerHillery/pypacktrends/issues/32">docker-compose.yml isn’t found during cloud init start up</a>, so when the VPS is first provisioned, I have to SSH into the VPS and run the command manually.</p>
<p>The update_service.sh script also hasn’t been thoroughly tested. If something goes wrong in the middle of the script, it could result in downtime for the web app.</p>
<p>Additionally, the updated container name variable for the Caddy container isn’t persisted, so if there’s an issue and Caddy restarts, it could lead to problems with the container.</p>
<p>Some changes to the docker-compose.yml file or upgrades to the Caddy image will still require downtime.</p>
<p>Another gap, I still need to implement tests, but I’ve already outlined my testing plans in detail in <a href="https://www.tylerhillery.com/blog/tyler-tries-to-automate-testing/">Tyler Tries to Automated Testing</a>.</p>
<p>But remember, this is CI/CD for a $5 VPS, you’ll have to wait until I come up with CI/CD for a $10 VPS to solve these problems.</p>
</section>
<section id="acknowledgements" class="level2">
<h2 class="anchored" data-anchor-id="acknowledgements">Acknowledgements</h2>
<ul>
<li><a href="https://github.com/fastapi/full-stack-fastapi-template">full-stack-fastapi-template</a>: I didn’t use this template directly, but I often refer to it for setup guidance on repository structure, GitHub Actions, development.md, config handling, and more.<br>
</li>
<li><a href="https://www.youtube.com/playlist?list=PLLnpHn493BHHAxTeLNUZEDLYc8uUwqGXa">Syntax Self Host 101 Playlist</a>: Helpful information on setting up a VPS.</li>
<li><a href="https://www.youtube.com/playlist?list=PLbKN2w7aG8EIbpIcZ2iGGsFTIZ-zMqLOn">Tailscale Infrastructure as Code Playlist</a>: Great resource on setting up a VPS with IaC and Tailscale.</li>
<li><a href="https://tailscale.com/kb/1276/tailscale-github-action">Tailscale GitHub Action</a>: How to use Tailscale’s GitHub Action and set up an OAuth client.</li>
<li><a href="https://youtu.be/jFrGhodqC08?si=CCiQYRmts3zmvDdR">Tom Delalande The cloud is over-engineeered and overpriced</a>: The inspiration behind my <code>update_service.sh</code> script</li>
<li><a href="https://youtu.be/-cEn_83zRFw?si=i_eTTaGHbmbDVc3N">Rails World 2024 Opening Keynote - David Heinemeier Hansson</a>: How to secure a VPS cheat sheet.</li>
<li><a href="https://www.pulumi.com/blog/executing-remote-commands">Executing Remote Commands with Pulumi</a>: Where I learned about Pulumi’s remote command feature.</li>
<li><a href="https://developers.cloudflare.com/pulumi/tutorial/add-site">Cloudflare Pulumi Tutorial</a>: Tutorial on how using pulumi with Cloudflare resources.</li>
</ul>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><a href="https://www.youtube.com/watch?v=-cEn_83zRFw">Rails World 2024 Opening Keynote - David Heinemeier Hansson</a>↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>DevOps</category>
  <category>Testing</category>
  <category>CI</category>
  <guid>https://www.tylerhillery.com/blog/cicd-for-your-vps/</guid>
  <pubDate>Mon, 11 Nov 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Shifting Left</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/shifting-left/</link>
  <description><![CDATA[ 




<hr>
<p>Shifting left in data refers to addressing issues in a data pipeline as close as possible to where the data is produced. Data pipelines are responsible for the movement of data from source to destination, with sources drawn on the left, hence “shifting left.”</p>
<p>Sources could be anything from your application database, CRM, billing system, etc. Destinations are typically a data warehouse, but the data doesn’t stop there. Transformations are then done in the data warehouse to make the data into a more usable format for downstream reporting or enriching data in other systems.</p>
<p>I graduated college with a degree in finance and intended to pursue a career path in investment management. I landed my first job out of college in a back-office role in the investment department of a mid-size insurance company.</p>
<p>This role gave me my first exposure to programming and databases. I automated mundane tasks that took our team several hours every week down to a few minutes. This experience was a revelation, showing me how technology could solve real-world problems. But more importantly, it demystified the black boxes I once thought computers were.</p>
<p>It has given me a new appreciation for all the technology surrounding us. I sit here typing this blog post on my laptop, seeing characters appear on my screen, while those changes are reflected realtime in a local version of my website. This shit is mind-blowing to me.</p>
<p>The most mind-blowing part isn’t the technology itself. It’s the fact that behind all of this technology are people who built it, people who are no different from you or me. This realization prompted me to switch careers.</p>
<p>Going to college for 4 years and then deciding 1 year after to change career paths is no easy decision. I didn’t want to start over, return to school, or take time off to do a bootcamp. Being a young, recent college grad with few responsibilities, I had one major advantage, time. I did not need to become a developer in as little as “3 months”. I was in it for the long haul.</p>
<p>Given my current background, I evaluated my skill set to see which technical roles I could get. The data space appealed to me because it’s the middle ground between the technical and business domains. It’s an area where I could leverage my finance background and newfound technical interests.</p>
<p>Most people view career paths as a ladder with a single axis, you can go up or down. I didn’t view my career that way. Instead, I saw it as a series of diagonal moves, each role being more technical than the last, shifting left and moving up the pipeline.</p>
<p>It’s been over 3 years since I decided to switch career paths. I went from that back-office investment role to a Business Intelligence Developer, Analytics Engineer, and my current role as a Data Engineer. Writing this now, 3 years doesn’t seem like a long time, but boy, it has felt like an eternity.</p>
<p>While recently rewatching my favorite movie, The Shawshank Redemption, Andy Dufresne’s journey resonated with me.</p>
<div class="callout callout-style-simple callout-caution">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p><em>Spoilers ahead</em></p>
</div>
</div>
</div>
<p>Andy, armed with nothing more than a rock hammer, spent nearly 20 years patiently chipping away at the walls of his prison cell, eventually tunneling a hole that would lead to his escape through a sewer pipeline. What resonates most about Andy’s journey is his patience, persistence, and meticulous nature. It also showcases the slow but steady journey of self-discovery.</p>
<p>Instead of a rock hammer, I have been armed with something much more powerful, a computer and the internet. While Andy was tunneling through walls, I was tunneling through the layers of abstraction, chipping away the black boxes of technology that once felt incomprehensible.</p>
<p>Unlike Andy, who emerged with a clear plan, my journey isn’t complete. I’m still figuring out what I want to do in tech.</p>
<p>I’ve enjoyed my time in various data roles, but something inside of me stills yearns for more. My experience in data was merely a gateway to something else I have yet to discover. I am in no rush though, I’m only year 3 into my 20 year escape.</p>
<p>Confidence is the most valuable thing I have gained over the past three years. Given enough time and pressure, I can learn anything I want. That’s all it really takes is time and pressure. Well, that and a big goddamn poster.</p>



 ]]></description>
  <category>Career Advice</category>
  <guid>https://www.tylerhillery.com/blog/shifting-left/</guid>
  <pubDate>Sun, 27 Oct 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Immerse Yourself</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/immerse-yourself/</link>
  <description><![CDATA[ 




<hr>
<p>When I started out my career in finance, I learned a valuable lesson while studying for the CFA exam. I learned this from Mark Meldrum, who was the CFA prep provider I used to help study for the exam. One of things he stressed was immersing yourself in the domain.</p>
<p>This can be done through numerous outlets such as watching the news or listening to a podcast. I distinctly remember Mark including a “Jelly Beans” section on his website which has links to movies, documentaries and university lectures. My two favorite resources at the time were Mark Meldrum’s Market Outlook on YouTube and the Bloomberg Surveillance news show.</p>
<p>One major benefit I gained from this was picking up the jargon of the domain. Many jobs have this unspoken language you are expected to know and there is no Duolingo course you can learn from. This language is only learned through experience.</p>
<p>Another key benefit was seeing the concepts being applied in real world scenarios. We’ve all sat in class wondering, “When will I use this?” but this experience eliminated that feeling.</p>
<p>It also transformed me into an active learner. Encountering familiar terminology in practice helped jog my memory and deepen my understanding, as I connected the dots between theory and application.</p>
<p>I carried this same practice when I transitioned into a career in tech. However, I quickly realized immersing yourself in the tech community is much different than the finance world. The news travels in unique ways and there are many pockets of specialized domains.</p>
<p>By far the biggest resource for me has been Twitter. To this day I am shocked by the people I get to interact with on the platform, from creators of well known open source libraries to CEOs. It has been arguable the most important part of my career because of the connections I have made.</p>
<p>Twitter is what you make of it though. The algorithm feeds you the content you interact with. I strictly use the “For You” feed so I get exposed to content outside of my circle. To have a good feed though it’s important to curate it. One of the first things I did when I decided to go all in on immersing myself in tech was to unfollow any account posting unrelated content.</p>
<p>If you find a hard time figuring out who to follow I recommend finding a few people you find interesting and looking at who they follow. There are too many people I want to call out so you can check out my following list <a href="https://x.com/_TylerHillery/following">here</a>.</p>
<p>An interesting aspect of tech is the many communities within it. I initially became involved in the data community, primarily engaging through the dbt and Locally Optimistic Slack. The dbt slack was how I discovered the Senior Analytics Engineer role at Nasdaq. I reached out to the hiring manager who posted the position in the jobs channel to express my interest which helped me get pass the initial resume screening phase.</p>
<p>This is another key benefit you will find while immersing yourself in your domain. You’ll make invaluable connections that can open doors to opportunities you might not have encountered otherwise.</p>
<p>Every community seems to have there go to hang out spot. I encourage you to find the hang out spot in your community and if there isn’t one create one!</p>
<p>They are many other ways to immerse yourself as well. Watch a documentary, read a book, listen to podcast. If you are looking for some resources to help immerse yourself checkout my newly created <a href="https://tylerhillery.com/lists">Lists</a>, where I shared the podcasts &amp; blogs I currently follow.</p>
<p>After years of immersing yourself, you’ll be shocked at how in tune you feel with the domain.</p>



 ]]></description>
  <category>Career Advice</category>
  <guid>https://www.tylerhillery.com/blog/immerse-yourself/</guid>
  <pubDate>Sat, 28 Sep 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Tyler Tries to Automate Testing</title>
  <dc:creator>Tyler Hillery</dc:creator>
  <link>https://www.tylerhillery.com/blog/tyler-tries-to-automate-testing/</link>
  <description><![CDATA[ 




<hr>
<section id="tldr" class="level2">
<h2 class="anchored" data-anchor-id="tldr">TL;DR</h2>
<p>I have implemented some <a href="https://github.com/TylerHillery/sql-translate/tree/main/.github/workflows">GitHub Actions</a> that runs <a href="https://github.com/pre-commit/pre-commit">pre-commit</a> which checks the following:</p>
<ul>
<li>Trailing whitespace</li>
<li>Ensures files end in a new line</li>
<li>Verifies proper yaml syntax</li>
<li>Ensures no debug statements were left behind</li>
<li>Checks that python test files are named properly</li>
<li>Runs the <a href="https://docs.astral.sh/ruff/linter/">ruff linter</a> and <a href="https://docs.astral.sh/ruff/formatter/">ruff formatter</a></li>
<li>Runs <a href="https://mypy.readthedocs.io/en/stable/">mypy</a> a static type checker</li>
</ul>
<p>Next, it runs <a href="https://docs.pytest.org/en/7.1.x/contents.html#">pytest</a> to run python tests and <a href="https://coverage.readthedocs.io/en/7.5.3/">Coverage.py</a> to measure code coverage.</p>
<p>Lastly, it runs <a href="https://github.com/samuelcolvin/smokeshow">smokeshow</a> which is used to create a temporary website based on the code coverage report. This enables the ability to use <a href="https://github.com/samuelcolvin/coverage-badge">coverage badge</a> to show the code coverage percent badge in the README.md file.</p>
</section>
<section id="inspiration" class="level2">
<h2 class="anchored" data-anchor-id="inspiration">Inspiration</h2>
<p>Whenever I look at a python repos such as: <a href="https://github.com/tiangolo/fastapi">FastAPI</a>, <a href="https://github.com/pydantic/pydantic">Pydantic</a>, <a href="https://github.com/Textualize/rich">rich</a></p>
<p>I was always curious as to how they were able to display badges in the README.md which showed information such as tests passing, code coverage, version etc. Something about these badges gave of this instant feel of a polished project. The little details matter.</p>
<p>I wanted to start adding some polish to my own projects so I dove a little deeper into how I can implement this myself, but where do I start?</p>
<blockquote class="blockquote">
<p>“good artists borrow, great artists steal.” - <em>Pablo Picasso</em></p>
</blockquote>
<p>With most new things I learn, I personally start with a concrete example. A reference point that I use as a blueprint for what I am trying to build. This helps me overcome <a href="https://veryprivategallery.com/blank-canvas-syndrome/#:~:text=A%20condition%20primarily%20associated%20with,to%20make%20work%20for%20years.">blank canvas syndrome.</a></p>
<p>My favorite way of finding examples is by looking at prominent people in the domain and see how they do it. For python projects I personally like to look at projects by:</p>
<ul>
<li><a href="https://github.com/charliermarsh">Charlie Marsh</a></li>
<li><a href="https://github.com/asottile">Anthony Sottile</a></li>
<li><a href="https://github.com/willmcgugan">Will McGugan</a></li>
<li><a href="https://github.com/tiangolo">Sebastián Ramírez</a></li>
<li><a href="https://github.com/simonw">Simon Willison</a></li>
<li><a href="https://github.com/tconbeer">Ted Conbeer</a></li>
<li><a href="https://github.com/dwreeves">Daniel Reeves</a></li>
<li><a href="https://github.com/samuelcolvin">Samuel Colvin</a></li>
<li><a href="https://github.com/pamelafox">Pamela Fox</a></li>
</ul>
<p>There are so many others and I encourage you to leave a comment of some of your favorite people in the python space!</p>
<p>For this project I used the <a href="https://github.com/tiangolo/full-stack-fastapi-template">full-stack-fastapi-template</a> as my main reference.</p>
</section>
<section id="pre-commit" class="level2">
<h2 class="anchored" data-anchor-id="pre-commit">Pre-commit</h2>
<p>I have grown very fond of pre-commit to run my static analysis tests. It makes it really nice to run all sorts of checks and it manages the installation of any tools needed. A great example is ruff, my goto python linter and formatter. Ruff already has <a href="https://github.com/astral-sh/ruff-pre-commit">ruff-pre-commit</a> which makes it as easy as adding the following lines to my <code>.pre-commit-config.yaml</code> file to run ruff as a pre-commit hook.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> repo: https:<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span>github.com<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>astral<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>sh<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>ruff<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>pre<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>commit</span>
<span id="cb1-2">    rev: v0<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">.4.8</span></span>
<span id="cb1-3">    hooks:</span>
<span id="cb1-4">      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>: ruff</span>
<span id="cb1-5">        args:</span>
<span id="cb1-6">          <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span>fix</span>
<span id="cb1-7">      <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>: ruff<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span></span></code></pre></div></div>
</section>
<section id="testing-and-code-coverage" class="level2">
<h2 class="anchored" data-anchor-id="testing-and-code-coverage">Testing and Code Coverage</h2>
<p>Testing can be a controversial topic for many developers… and to be honest it’s an area I need to improve on. Recently, I have actually grown to like it. There is something about running tests and seeing all green that is so so satisfying.</p>
<p><img src="https://www.tylerhillery.com/assets/images/pytest.png" class="img-fluid"></p>
<p>Pytest is the defacto standard when it comes to implementing tests in python. I am less experienced with code coverage and this was actually the first time I had used Coverage.py or any code coverage tool for that matter.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>I need to come back and look into how Coverage.py figures out code coverage percentage</p>
</div>
</div>
<p>To get the badges to display in the README.md file I copied the links from the fastapi-template replacing the urls with my repository url and I added the <code>smokeshow.yml</code> GitHub Action which creates the temporary website from the code coverage html report so the code coverage badge can display the percentage.</p>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>You can use <a href="">pipx</a> to run python commands without having to install the package</p>
<p><code>pipx run smokeshow generate-key</code></p>
</div>
</div>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>I have noticed in other people’s GitHub Action files that <code>${{ secrets.GITHUB_TOKEN }}</code> is referenced. I always tried to create a secret with that name in my repository with a GitHub token value. But it would error out saying you can’t have a secret that starts with GitHub. Well, it turns out this secret is already created for you and you don’t need to create anything.</p>
</div>
</div>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>This blog post was written primarily so I can refer back to how I did this. Making it public so others can hopefully get something out of my experience. More importantly I wanted to shared how I approached doing something I have never done before.</p>


</section>

 ]]></description>
  <category>DevOps</category>
  <category>Testing</category>
  <category>CI</category>
  <guid>https://www.tylerhillery.com/blog/tyler-tries-to-automate-testing/</guid>
  <pubDate>Fri, 14 Jun 2024 00:00:00 GMT</pubDate>
  <media:content url="https://www.tylerhillery.com/assets/images/github-ci-badge.png" medium="image" type="image/png" height="77" width="144"/>
</item>
</channel>
</rss>
