<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tools to help diagnose and pinpoint Node.js performance issues]]></title><description><![CDATA[Clinic.js is a suite of tools to help diagnose and pinpoint your Node.js performance issues.]]></description><link>https://clinicjs.org</link><image><url>https://clinicjs.org/assets/images/clinic.png</url><title>Tools to help diagnose and pinpoint Node.js performance issues</title><link>https://clinicjs.org</link></image><generator>GatsbyJS Material Starter</generator><lastBuildDate>Tue, 02 Jan 2024 14:41:12 GMT</lastBuildDate><atom:link href="https://clinicjs.org/rss.xml" rel="self" type="application/rss+xml"/><copyright><![CDATA[Copyright © 2019 NearForm]]></copyright><item><title><![CDATA[Introducing Bubbleprof - a novel approach to Node.js async profiling]]></title><description><![CDATA[Since the beginning of Node, profiling asynchronous operations has been a big
hurdle. After months of internal research we have finally…]]></description><link>https://clinicjs.org/blog/introducing-bubbleprof/</link><guid isPermaLink="false">https://clinicjs.org/blog/introducing-bubbleprof/</guid><dc:creator><![CDATA[Alan Slater, Kamil Mech, Mathias Buus, Matteo Collina]]></dc:creator><content:encoded>&lt;div&gt;&lt;video src=&quot;/assets/videos/bubbleprof-screen-recording.mp4&quot; playsinline loop autoplay muted&gt;&lt;/video&gt;&lt;/div&gt;
&lt;p&gt;Since the beginning of Node, profiling asynchronous operations has been a big
hurdle. After months of internal research we have finally found a solution which
greatly simplifies the process of finding async bottlenecks in Node
applications. Today, we are glad to announce the first public version of Clinic.js
Bubbleprof. Bubbleprof allows developers to capture all async activity with
minimum effort. It then uses a novel &quot;bubble&quot; approach to visualize this
activity. Everything you need is in one HTML file.&lt;/p&gt;
&lt;p&gt;You can find it included in the &lt;a href=&quot;http://clinicjs.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Clinic.js&lt;/a&gt; bundle:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install -g clinic&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Try it out by cloning our basic Bubbleprof examples from Github:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;git clone git://github.com/clinicjs/node-clinic-bubbleprof-examples&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Start simple and run the &lt;code class=&quot;language-text&quot;&gt;basic-latency&lt;/code&gt; example, which visualizes how a latency
of 1s affects your server:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;clinic bubbleprof --on-port ‘autocannon localhost:$PORT’ -- node node-clinic-bubbleprof-examples/basic-latency&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice the long lines of latency? That’s a quick way of finding something to
improve in the app.&lt;/p&gt;
&lt;h2 id=&quot;traditional-async-profiling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#traditional-async-profiling&quot; aria-label=&quot;traditional async profiling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Traditional Async Profiling&lt;/h2&gt;
&lt;p&gt;Node works best in heavily-I/O-related contexts, and often acts as a mediator
between many data streams and interfaces. Due to JavaScript’s evented nature,
most I/O is performed asynchronously – especially when our Node process is a
networked application. If we can measure asynchronous activity in a decoupled
way, we can find out where an application is waiting. Finding out where an
application is waiting means finding out where to optimise our asynchronous
flow. The end result being that our application becomes faster, and our users
happier.&lt;/p&gt;
&lt;p&gt;Tracking and profiling asynchronous is a tricky issue. Consider the following
simple example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// maybe crash after 1s&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// call it again&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;crash&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘an &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; error’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running the above program will (probably) crash our Node.js process with a stack
like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;set-timeout-crash.js:5
  throw new Error(&apos;an async error&apos;)
  ^

Error: an async error
    at Timeout.crash [as _onTimeout] (set-timeout-crash.js:5:9)
    at ontimeout (timers.js:466:11)
    at tryOnTimeout (timers.js:304:5)
    at Timer.listOnTimeout (timers.js:267:5)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Figuring out which one of the &lt;code class=&quot;language-text&quot;&gt;setTimeout&lt;/code&gt;s triggered the crash is a
surprisingly hard problem. The stack trace only contains the last synchronous
part of our application. If we want to not just figure out what crashed the
program but also profile how many times the async function is called and from
where we would run into similar problems.&lt;/p&gt;
&lt;p&gt;This is not a new problem in Node.js, but in fact one that’s been around since
the very beginning. Lots of solutions have been attempted for making the
situation better in regards to capturing longer stack traces and measure runtime
of functions. Most older solutions did things like rewrite all your code that
does something async to capture a stack trace before and then combine them back
to produce a “full” trace. This requires plenty of “monkey patching” and is
known for being brittle and have a substantial negative performance effect - it
would often de-optimise your code because of too much reflection.&lt;/p&gt;
&lt;h2 id=&quot;enter-node-core-instrumentation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#enter-node-core-instrumentation&quot; aria-label=&quot;enter node core instrumentation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Enter node core instrumentation&lt;/h2&gt;
&lt;p&gt;Luckily the Node.js core collaborators have been trying hard to make the
diagnostic situation better for everyone by adding more instrumentation to the
Node.js core codebase. In fact, all async code (excluding native modules) is
actually triggered from Node.js core which means that the situation has to
improve there for userland to get any benefit. Some of the new instrumentation
that has landed recently is the new &lt;code class=&quot;language-text&quot;&gt;async_hooks&lt;/code&gt; core module. &lt;code class=&quot;language-text&quot;&gt;async_hooks&lt;/code&gt; is
an interface to a new set of instrumentation in core that instruments any async
operation. This means that we now have a way to hook into &lt;em&gt;when&lt;/em&gt; something async
happens and also a way to find out what the &lt;em&gt;parent&lt;/em&gt; async operation was. This
is a massive improvement in the profiling landscape as it means we can now get a
ton of valuable timing data out of Node.js core without having to resort to a
bunch of hacks.&lt;/p&gt;
&lt;p&gt;If we add some &lt;code class=&quot;language-text&quot;&gt;async_hooks&lt;/code&gt; magic to our previous example, then we can figure
out which of the &lt;code class=&quot;language-text&quot;&gt;setTimeout&lt;/code&gt;s made our program crash:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hooks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;async_hooks&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stacks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

hooks
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHook&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// save the stack when we do something async&lt;/span&gt;
    &lt;span class=&quot;token function-variable function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; trigger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stacks&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// maybe crash after 1s&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crash&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// call it again&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;crash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// lookup the previous stack&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stacks&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;hooks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executionAsyncId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;an async error&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running it will show something similar to this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    at AsyncHook.init
    …
(set-timeout-crash-hook.js:11:1)
    ...
Error: an async error
    at Timeout.crash [as _onTimeout] (set-timeout-crash-hook.js:17:11)
    at ontimeout (timers.js:466:11)
    at tryOnTimeout (timers.js:304:5)
    at Timer.listOnTimeout (timers.js:267:5)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which tells us that this time it was the timeout at line 11 (first one) that
triggered the crash.&lt;/p&gt;
&lt;p&gt;In addition to letting us capture the async context async_hooks gives us
valuable insights into latency stats, throughput, the type of resource, and
more.&lt;/p&gt;
&lt;h2 id=&quot;reducing-complexity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reducing-complexity&quot; aria-label=&quot;reducing complexity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reducing complexity&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;async_hooks&lt;/code&gt; and other new core instrumentation give us a new waterhose of
profiling data in Node.js. This is essential for doing any kind of profiling but
also poses an interesting challenge. How do we digest this data in a way that
helps us diagnose bottlenecks and/or find errors in our application? This, of
course, is a non-trivial problem and depends on the use-case we are trying to
support.&lt;/p&gt;
&lt;p&gt;This is why we’ve started building Bubbleprof, a new command in the
&lt;a href=&quot;https://github.com/clinicjs/node-clinic&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Clinic.js&lt;/a&gt; toolchain. Bubbleprof uses a
series of heuristics and a novel “bubble” based UI to help all kinds of users -
from beginners to advanced - to determine where asynchronous time is spent in
their application.&lt;/p&gt;
&lt;p&gt;Through a series of design workshops we’ve come up with a couple of heuristics
we think help group async data together in a way that makes it easy to get an
overview over your application.&lt;/p&gt;
&lt;p&gt;There are 3 interesting groupings of code in your Node.js application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;User code&quot;, ie. code you are writing as part of your app.&lt;/li&gt;
&lt;li&gt;&quot;Module code&quot;, code running in modules you have installed from npm&lt;/li&gt;
&lt;li&gt;&quot;Node core code&quot;, code running in Node.js core.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When code crosses the boundary between one of these groupings, we consider it
important information that can help us group asynchronous operations together.
Bubbleprof tries to collect and aggregate &lt;em&gt;all&lt;/em&gt; async operations (using
&lt;code class=&quot;language-text&quot;&gt;async_hooks&lt;/code&gt;) and then group them into bubbles based on this heuristic.&lt;/p&gt;
&lt;h2 id=&quot;visualizing-async-flow&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#visualizing-async-flow&quot; aria-label=&quot;visualizing async flow permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Visualizing async flow&lt;/h2&gt;
&lt;p&gt;Now that we have a manageable number of groupings - instead of hundreds or
thousands of distinct async operations - we can draw a diagram that acts like a
map of an application&apos;s async flow, showing where time is spent. For example, in
this profile based on ACMEair (a dummy flight data application designed for use
in benchmarking), we immediately see a flow centered around the database module
MongoDB:&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c4291bbebb88963c86f5a889a85bd17a/d8c86/2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block;  max-width: 1100px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.72727272727272%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABYElEQVQoz32SSU4kMRBF8xhkeh4iPedQ6XJWF+oFrRYL2HIJNuy4EL3uO7YpiiFphPQVshR6jh/fbo5Xt+vlbz8cTNj3Pn+rvUsHG8u4/Ly+ucuHXw2VUfaTtjNVsaMGMUu4Q/VQ61ZYBvCLglHCJExmOjUdq4BpCdRKpRc6yVhYyIhbdGq9iYgAw0rdjM2AdcLcNy8NpoKAxKSnEGnKLBXmJ0z7DcyDGg9sKXxZRcpEvMJYOMxMx+o0x1MWqcR0SaX7CGPhpZt6O4OZpE5EuDPcnZbE3HUE1LhH3DBZjW1h7vv90YQduBns9A6/XtEzHfvd2j0b3nhGtCcw6HwEOyoz1h0xtxu4xSD9DHNpkf4qMG/8LgzFpazMUNPdTq6eh0wgom1UZ1gGG7MdVhMLhFyftvnkTaTl/5lncXuB5AVWLVYd0VXNNhJb9fxDPmOu7TiU2+vHv1cPf37cPx1P+gc/8GM3aHs2zwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Example 2&quot;
        title=&quot;&quot;
        src=&quot;/static/c4291bbebb88963c86f5a889a85bd17a/99f37/2.png&quot;
        srcset=&quot;/static/c4291bbebb88963c86f5a889a85bd17a/6b2ea/2.png 275w,
/static/c4291bbebb88963c86f5a889a85bd17a/dd45a/2.png 550w,
/static/c4291bbebb88963c86f5a889a85bd17a/99f37/2.png 1100w,
/static/c4291bbebb88963c86f5a889a85bd17a/573d3/2.png 1650w,
/static/c4291bbebb88963c86f5a889a85bd17a/d8c86/2.png 1663w&quot;
        sizes=&quot;(max-width: 1100px) 100vw, 1100px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/assets/html/bubbleprof-example.html&quot;&gt;Live example&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;bubbles-and-links&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bubbles-and-links&quot; aria-label=&quot;bubbles and links permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Bubbles and links&lt;/h3&gt;
&lt;p&gt;These &quot;bubbles&quot; represent the time spent in synchronous and asynchronous
operations within this grouping. The largest bubble in the view represents calls
from the &lt;code class=&quot;language-text&quot;&gt;mongodb-core&lt;/code&gt;, which calls other functions elsewhere in the &lt;code class=&quot;language-text&quot;&gt;mongodb&lt;/code&gt;
code. It dwarves every other bubble, which compared to it are tiny dots, and
much of the application branches off from it. Clearly, optimising how this
application uses &lt;code class=&quot;language-text&quot;&gt;mongodb&lt;/code&gt; has a lot of potential to reduce overhead and trigger
other async operations earlier. The dominating green colouring in the inner ring
tells us that most of this time is spent on network-related activities, while
the small sliver of purple indicates some time spent in scheduling (ticks,
timeouts and promises). Rolling the mouse over the labels for these colours
gives us information on what they mean and highlights the appropriate parts of
the diagram.&lt;/p&gt;
&lt;p&gt;There is also a very long line to a tiny bubble labelled &lt;code class=&quot;language-text&quot;&gt;nextTick + http.server&lt;/code&gt;. A thin white stripe tells us that this is code from our own
application. Connecting lines like this one represent asynchronous delays from
operations that were called in one grouping (here, the &lt;code class=&quot;language-text&quot;&gt;mongodb&lt;/code&gt; module), but
execute code in another (here, some of our application&apos;s own code which involves
an &lt;code class=&quot;language-text&quot;&gt;http&lt;/code&gt; server and &lt;code class=&quot;language-text&quot;&gt;nextTick&lt;/code&gt; wrappers). This suggests another area for us to
focus on: our own code, which might be a quick win.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dd8f947647f0243da9a0f2ba5e798c2a/d8c86/3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block;  max-width: 1100px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.36363636363636%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAABXElEQVQoz12RyU7DMBCGI4FUloLKAULi3Um8xEncZqGlBYGAC9y4cCi8/3MwAVSSSt9hpPEn/zMTmO5x8/R2s352fqWLTuVN1lNnf8UI41e5X5b1+uX1fbl5Dq7iBPGcpSXPKiJyxAzmlvAc0b5AYxK7EGnJZEnTOU3KIMIpYhqIqYLXLHFCeVHdIl3FVP+2dkjXcdcg7XFWYZ4HuwYHLSsIN0RVqOyYX7G0GMlUS9uSZokb6HZUuH8Zc9MXfWZLfavcSukmZmrgG+lqY3tS7akc/PzjW4jKtE98h4hicvwzyM1aFXVm5gAVdiQjbmAFIRYhlbOL8PKagDCURdXpqlV2wWHAPRmShxE/PJocTI8Pjicnp2d/s/xulGm4JVwUUK6F6wR7wSKcRJjGhE3PZ9Oz2VD+WWouUsfTAsBc78mQXEcQnpirWIaxGKxaYen05sM+fKm7rbrf6vvPb/RBVPzjIxpaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Example 2&quot;
        title=&quot;&quot;
        src=&quot;/static/dd8f947647f0243da9a0f2ba5e798c2a/99f37/3.png&quot;
        srcset=&quot;/static/dd8f947647f0243da9a0f2ba5e798c2a/6b2ea/3.png 275w,
/static/dd8f947647f0243da9a0f2ba5e798c2a/dd45a/3.png 550w,
/static/dd8f947647f0243da9a0f2ba5e798c2a/99f37/3.png 1100w,
/static/dd8f947647f0243da9a0f2ba5e798c2a/573d3/3.png 1650w,
/static/dd8f947647f0243da9a0f2ba5e798c2a/d8c86/3.png 1663w&quot;
        sizes=&quot;(max-width: 1100px) 100vw, 1100px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/assets/html/bubbleprof-example.html&quot;&gt;Live example&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;drilling-down-to-code&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#drilling-down-to-code&quot; aria-label=&quot;drilling down to code permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Drilling down to code&lt;/h3&gt;
&lt;p&gt;We can click into these links and bubbles to see what is going on inside them.
Clicking on the line shows something very simple: &lt;code class=&quot;language-text&quot;&gt;startServer&lt;/code&gt; is responsible
for almost all of the delay in this grouping. Clicking again brings up the stack
trace; and also - because context here is important - the complete async trace
of the chain of events from our application&apos;s initiation to this point.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/87e046a267779a2874f4bb482798a0b1/d8c86/4.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block;  max-width: 1100px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.72727272727272%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABr0lEQVQoz33R3W6bMBQHcJ5iCgTChwEbzDfmMxCWpLCUhnRd22XrKrXqXS+mXewZ9iLb3Z5yp8mGok2a9JNlrPM3xzZXLvu0XNlehh1m0vh/HGZ5GXETj1Vdf83yJSeqVNKoToIZcgSFTOUDxfqLIBNBxgZlyPQ1M1QJk3WXE2bmVMaH8WUy02wo4iUD5qegAPI6ZZLhCRoVNVtULO60QlSIgqjuMp3G/+YllarQIPFky1eIL6kWB4ERNMyLOqIRDovJVIe9f5/iAE6H7BDbkWmFmuFJqs1NRB0CvHQcjckUydizk/lEQPzMgJXRRMJmUmIaGVZgkODlz3HRRXkb5y3Lz5ywpn5NoyauNjSoTznBom7fojg3iI+wrxoudMqttg/t8LA+v1u+eV80l2k9ZNWQVkNW70bwWTRXV/snSFI/s1yGsAdXyzXdfjPctxcfVxBeQOlwlMz7E+dZvb28eTTtiHg5dlJ4M3habtF9WPaf6vV10exGabUFyfziiJV9tti92z+94mVeRECQdMCV69vXm7v67AYyxzowxv7YJkV3//nb+uvP1ZcfxfP38uAX/ZF9sadIG0UAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Example 3&quot;
        title=&quot;&quot;
        src=&quot;/static/87e046a267779a2874f4bb482798a0b1/99f37/4.png&quot;
        srcset=&quot;/static/87e046a267779a2874f4bb482798a0b1/6b2ea/4.png 275w,
/static/87e046a267779a2874f4bb482798a0b1/dd45a/4.png 550w,
/static/87e046a267779a2874f4bb482798a0b1/99f37/4.png 1100w,
/static/87e046a267779a2874f4bb482798a0b1/573d3/4.png 1650w,
/static/87e046a267779a2874f4bb482798a0b1/d8c86/4.png 1663w&quot;
        sizes=&quot;(max-width: 1100px) 100vw, 1100px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/assets/html/bubbleprof-example.html#a49&quot;&gt;Live example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because these traces can be very long, we group adjacent frames from the same
section of code, automatically expanding those from the user&apos;s own application.
In this example, &lt;code class=&quot;language-text&quot;&gt;startServer&lt;/code&gt; at line 192 of our &lt;code class=&quot;language-text&quot;&gt;app.js&lt;/code&gt; called the &lt;code class=&quot;language-text&quot;&gt;express&lt;/code&gt;
module, which invoked a number of operations in node core, with
&lt;code class=&quot;language-text&quot;&gt;createServerHandle&lt;/code&gt; being the last one. This was called from the &lt;code class=&quot;language-text&quot;&gt;mongodb&lt;/code&gt;
client.&lt;/p&gt;
&lt;p&gt;Looking at the area chart on the right, we see that this was pending for most of
the runtime of our application. Is this a slow server we want to optimise, or a
healthy service constantly awaiting requests? We can check our application code
and find out.&lt;/p&gt;
&lt;p&gt;We can click the upwards-pointing arrow labelled &quot;Mongo...&quot; to navigate up into
that big, &lt;code class=&quot;language-text&quot;&gt;mongodb-core&lt;/code&gt; bubble. The view inside it also very simple - dominated
by &lt;code class=&quot;language-text&quot;&gt;Connection.connect&lt;/code&gt;, called from within &lt;code class=&quot;language-text&quot;&gt;node_modules/mongodb-core&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/47246ce88a12e8167e5df65a55c93379/d8c86/5.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block;  max-width: 1100px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.72727272727272%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABH0lEQVQoz32SS07DMBCGc4w2fsbvZ0JSJ6WRWFRIXZQtl2DDjgvBmjviNgIBMUi/RhrPfJ7fI1fz8TzN967daz8ql/6TH23cmzB1u7vT+THdHivIPOZRmB7zUBMDqAV0iT+USzXR0u246pjsG5OIiFWNFSB6iYu2UNRYfqWLrg1GxhHpDoiQR0Jqq19NWehSMIXzxjOfcBhI3FF7g5o1jBWOCfEAvnn5hB2zvbKDND2TbU5XMJIkexNxDUPq1DhrP0h7I01x8l8wVki2Ih2k6bjuGhnz00q2/QCZK9rWbvDtZGPiusVsbZsoQHWNRHGRJiSTf0SYZN4cD4VtX/jV2Iuo2QC2gXwLeb49qwivMbutqZweTi/vx+e3w9PrfNUH0DphBpPwIJIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Example 4&quot;
        title=&quot;&quot;
        src=&quot;/static/47246ce88a12e8167e5df65a55c93379/99f37/5.png&quot;
        srcset=&quot;/static/47246ce88a12e8167e5df65a55c93379/6b2ea/5.png 275w,
/static/47246ce88a12e8167e5df65a55c93379/dd45a/5.png 550w,
/static/47246ce88a12e8167e5df65a55c93379/99f37/5.png 1100w,
/static/47246ce88a12e8167e5df65a55c93379/573d3/5.png 1650w,
/static/47246ce88a12e8167e5df65a55c93379/d8c86/5.png 1663w&quot;
        sizes=&quot;(max-width: 1100px) 100vw, 1100px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/assets/html/bubbleprof-example.html#c3&quot;&gt;Live example&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;navigating-async-complexity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#navigating-async-complexity&quot; aria-label=&quot;navigating async complexity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Navigating async complexity&lt;/h3&gt;
&lt;p&gt;So what about the parts of our &lt;code class=&quot;language-text&quot;&gt;mongodb&lt;/code&gt; integration that are fast? If we click
the small topmost grouping, it expands out into another more complex layout.
These tiny, extremely short async operations would have been too small to be
useful information in the previous view, so Bubbleprof has collapsed them
together.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3377d684dc4fb8d0cd397ca8c13e5478/d8c86/6.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block;  max-width: 1100px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.72727272727272%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABVklEQVQoz31RSU7DQBD0MxLP4tk3z9iOcZwFRSISyiFc+QQXbnwIzvyRdqyQ2EJIpdGMu6tdXZXtj+f+8dlXWxvXpuz+Q1xDm0t93R1O59due8wwL6lKTNeIubxwiPk/AaW8sLrspG2EWXG3LlTKcmpQYcfzArck6vJ01y92bAC+Cg9EJcQDYgEzn913oAI6dCEbwhJcpiVLRMlNQ3WkBpQmwqdkGAYASVRUeBR8X+VBhpUJrfGtMBXh4UbGImKRELXFaouEBy8A09HBrPe2bLVvtKvnf0ZUExH15omZBt1cGEuG6kp3O6BJW3OdMHO/ZIO5J7oR7iDVw6BKVfOdebChLaveJ/C8ouIm22EZiQAnehgE3iCQLeLMMBc7V21s7CEzKuNE9oKoMZVh/8GwSVrwXCCxwHKJZQ5xEjWL6s72wa3r2swvc9D0cvr4Pr5/7d4+9xf8AJWqYf0UOByDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Example 6&quot;
        title=&quot;&quot;
        src=&quot;/static/3377d684dc4fb8d0cd397ca8c13e5478/99f37/6.png&quot;
        srcset=&quot;/static/3377d684dc4fb8d0cd397ca8c13e5478/6b2ea/6.png 275w,
/static/3377d684dc4fb8d0cd397ca8c13e5478/dd45a/6.png 550w,
/static/3377d684dc4fb8d0cd397ca8c13e5478/99f37/6.png 1100w,
/static/3377d684dc4fb8d0cd397ca8c13e5478/573d3/6.png 1650w,
/static/3377d684dc4fb8d0cd397ca8c13e5478/d8c86/6.png 1663w&quot;
        sizes=&quot;(max-width: 1100px) 100vw, 1100px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/assets/html/bubbleprof-example.html#lclump:A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20,A21%7Cc3&quot;&gt;Live example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Exploring this view, we see activity mostly relating to database connection
pools and sockets. Everything looks fine in terms of speed, and we can use these
maps of how processes execute in series and parallel to better understand the
module&apos;s flow, diagnose timing bugs, spot operations in series that could be
more efficient in parrallel, and identify unnecessary steps that can be
optimised away.&lt;/p&gt;
&lt;p&gt;This is just a simple example. You can use Bubbleprof with benchmarking tools
like Autocannon or Wrk to generate robust performance profiles, and see the
changes in your application&apos;s throughput and flow as you try things out. We have
a
&lt;a href=&quot;/documentation/bubbleprof/&quot;&gt;simple step-by-step walkthrough guide&lt;/a&gt;
to help you get started.&lt;/p&gt;
&lt;h3 id=&quot;get-started&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#get-started&quot; aria-label=&quot;get started permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Get Started&lt;/h3&gt;
&lt;p&gt;We&apos;d love for you to install and try out Bubbleprof to see how it can help get
to the bottom of your Node.js performance issues.&lt;/p&gt;
&lt;p&gt;Head over &lt;a href=&quot;/documentation/bubbleprof/&quot;&gt;to the walkthrough&lt;/a&gt; and you&apos;ll be up and
running in minutes.&lt;/p&gt;
&lt;p&gt;We&apos;d also love to get your feedback on Bubbleprof/Doctor/Flame and the outputs
they generate. In this early phase of release, we&apos;re eager to have it used on as
many real-world problems as possible.&lt;/p&gt;
&lt;p&gt;We welcome everyone who is interested in becoming part of our community. If
you&apos;d like to get involved in any aspect, not just code, first read our
&lt;a href=&quot;https://github.com/clinicjs/node-clinic/blob/master/CODE_OF_CONDUCT.md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Code of Conduct&lt;/a&gt;
and
&lt;a href=&quot;https://github.com/clinicjs/node-clinic/blob/master/CONTRIBUTING.md&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Contributor guide&lt;/a&gt;.
Then feel free to reach out to us on GitHub or via the usual social channels.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Clinic.js Doctor just got more advanced with TensorFlow.js]]></title><description><![CDATA[At the start of 2018 we introduced Clinic.js, an Open Source toolbox for developers to profile and improve their applications. As part of…]]></description><link>https://clinicjs.org/blog/clinic-doctor-just-got-more-advanced-with-tensorflow-js/</link><guid isPermaLink="false">https://clinicjs.org/blog/clinic-doctor-just-got-more-advanced-with-tensorflow-js/</guid><dc:creator><![CDATA[Andreas Madsen]]></dc:creator><content:encoded>&lt;div&gt;&lt;style&gt;
figure {
  margin: 1.5em 0;
}

figure img {
  margin: 0 auto;
  display: block;
}

figure figcaption {
  font-size: 0.9em;
  margin-top: 1em;
}
&lt;/style&gt;&lt;p&gt;At the start of 2018 &lt;a href=&quot;https://www.nearform.com/blog/introducing-node-clinic-a-performance-toolkit-for-node-js-developers/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;we introduced Clinic.js&lt;/a&gt;, an Open Source toolbox for developers to profile and improve their applications. As part of this toolbox, we launched Doctor, a very user-friendly tool, that uses data analysis to recommend the next steps the user should take to diagnose and fix performance problems in Node.js. And just last month we shipped a new tool, called &lt;a href=&quot;https://www.nearform.com/blog/introducing-clinic-bubbleprof-a-unique-way-to-visualise-node-js-code/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Clinic.js Bubbleprof&lt;/a&gt;, which specializes in profiling I/O issues.&lt;/p&gt;&lt;p&gt;While we are developing new exciting tools, we are also making a significant effort in improving the existing tools we have. An issue we have noticed during our many workshops, where we teach people to use Clinic.js, is that the way Doctor analyzed the CPU usage wasn’t optimal. Until recently Doctor was using simple statistics to analyze the CPU usage, but now, with the experience we have gathered over the last half year, we have been able to develop much a more advanced Machine Learning model. This model is developed with &lt;a href=&quot;https://js.tensorflow.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;TensorFlow.js&lt;/a&gt;. Because TensorFlow.js uses JavaScript, Doctor is just as easy to install as always but is now much more advanced.&lt;/p&gt;&lt;figure&gt;
&lt;img alt=&quot;Doctor + Tensorflow&quot; src=&quot;/2dc138330e017a7e72d18a20daca63d1/doctor-tensorflow.svg&quot;&gt;
&lt;/figure&gt;&lt;h2 id=&quot;the-details&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-details&quot; aria-label=&quot;the details permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Details&lt;/h2&gt;&lt;p&gt;An application with an I/O issue typically has a very low CPU usage, because it is spending most of its time being idle. However, what we have noticed is that even applications with I/O issues generate garbage, that the garbage collector will clean up. When the garbage collector runs, it makes the CPU usage spike. If the garbage collector runs often enough, the CPU usage spikes so much that our simple statistical model can no longer see that the CPU usage is too low.&lt;/p&gt;&lt;figure&gt;
&lt;img alt=&quot;Doctor + Tensorflow&quot; src=&quot;/0e1766831e95d15420b269526b899191/gc-highlight.svg&quot;&gt;
&lt;figcaption&gt;
&lt;strong&gt;CPU usage, with GC overlay:&lt;/strong&gt; Shows the CPU usage with different types of garbage collection overlayed. Notice, that the alignment isn&amp;#x2019;t perfect and other events are interfering.
&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;In a simple world, one could just have used information about when garbage collection is happening to filter out the CPU spikes. Unfortunately, the CPU usage data is sample based while the garbage collection data is event-based, which makes it difficult to align the two data sources. From our investigation, it is also clear that other things are going one. Some possible causes could be optimization or writing the logging information itself. All are things that happen in another thread, therefore they make the CPU usage spike to above 100%.&lt;/p&gt;&lt;p&gt;Since it isn’t possible to consistently detect when another thread from V8 within the application makes the CPU usage spike, the solution was to separate the spiky data with Machine Learning. For this, we use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Hidden_Markov_model&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hidden Markov Model&lt;/a&gt; (HMM) with &lt;a href=&quot;https://en.wikipedia.org/wiki/Normal_distribution&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Gaussian&lt;/a&gt; Emissions. The central idea in HMM is that a measurable observation, the CPU usage, is influenced by a hidden unobservable state, is V8 is running an extra thread or not. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Baum%E2%80%93Welch_algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Baum–Welch algorithm&lt;/a&gt;, allows one to statistically determine what the most likely connection is between the hidden state and the measurable observations. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Viterbi_algorithm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Viterbi algorithm&lt;/a&gt; can then infer the hidden state from the measurable observations.&lt;/p&gt;&lt;p&gt;A trainable and inferable implementation of HMM with Gaussian Emissions didn’t exist in the npm register, therefore we ended up implementing it ourselves using &lt;a href=&quot;https://js.tensorflow.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;TensorFlow.js&lt;/a&gt;. The implementation is called
&lt;a href=&quot;https://www.npmjs.com/package/hidden-markov-model-tf&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;hidden-markov-model-tf&lt;/code&gt;&lt;/a&gt; and is available on npm.&lt;/p&gt;&lt;p&gt;It&apos;s fully Open Source and the sourcecode is &lt;a href=&quot;https://github.com/clinicjs/node-hidden-markov-model-tf&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;available here&lt;/a&gt;.&lt;/p&gt;&lt;figure&gt;
&lt;img alt=&quot;Doctor + Tensorflow&quot; src=&quot;/aeadab0054c5b092171ba40d5edb4dce/cpu-hmm.svg&quot;&gt;
&lt;figcaption&gt;
&lt;strong&gt;CPU usage filtered:&lt;/strong&gt; Shows the CPU usage from the user&amp;#x2019;s application itself, being correctly separated from the CPU usage spikes caused by V8.
&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;Using our implementation of the Hidden Markov Model, it is possible to separate the CPU usage caused by V8 from the CPU usage directly related to the user&apos;s application. With this separation in place, it is now possible to detect an I/O issue by checking if the CPU usage of the user’s application is too low.&lt;/p&gt;&lt;figure&gt;

  &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5363fe52234b34b1cfb3df90823e9be8/8ce52/doctor-screenshot.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
  
  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block;  max-width: 681px; margin-left: auto; margin-right: auto;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 107.63636363636364%; position: relative; bottom: 0; left: 0; background-image: url(&amp;apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAAsSAAALEgHS3X78AAADgElEQVQ4y42Ty47cRBSGvUSEkchMhm5Xlavsssuui6/d9kzf793pdCeToElQpEhZRYEgQEIiSkAsUKQQsWHFhhfgFbiEx+AS3objbgkFaRaRPv1yWfXXOf7r2DLbZX+8na3eb3cWMumqtHchUdwpu8vF+ny1uX391j3Yb9KBJbez08FqujjLy7EXFn7UrpFtoarXCWSZtkfj+Y3N2d3tzbvL9blOelbgFbkexMU4LSZFOS+qBWjenqlkKOPB68AbLtquF7s8sXGEHWkpcbI4uTFZfTCcnY8Wd6bLO+P57dH0PK/WaXuVtlZJsUxaS5Mv2p1tkk+zole0BuBHJLIi3Y5bvSTvGTcVx+LI9htN/z3bRzhs2oEI87IaJ2mnOhlnRR+RsGEHADjryr7IBDWeFzOqGVVkBwV1JHIk8wzzYsc1jGeUZ9hNCOClmOraDJUTW1MiYQFQB2xKYu1jRTwjdQlHIJYiapCjcE2EqaoBM4tyhbRPdES040iFjeuoCGtOFKJKhAVhce0hYQ0UgCUz+0rW2u8+O+i9OOh//87w+UH/x7dHP1wa/fTWJEOmQcPQdLEc2KKDRGevKKhs0UVeDmdZG955yKf3g8mHfPLIn30qFp/w2YNwLt2kSUJfFDLu6Wyo0r7OBiYf6qwfFyMetiBR69gJL3N5yNW7XF7m6kiYw0BfEQaz+qsgXkIlYxoidD3j8RjuGdRhCrKwOE8ET32ehkHO3RiSoxiIds6IusYLUtcHsjo5R+20Zpe2KvPWAK4eNM171NX7OwRsHHp+2ionWd7N8y7GAUZ+rcAuPIvHwyaRMA9NJGD33rYHeuNBaidXm+m6GS9xtsb5NZwscb7FQVkHxrM54RmhmjBDmMZ7qIbGoAuZDkh4SoIW4TnmRY2X4aDCfhvDePLqDPkVajBkc4xD6BnZHnI0TAUDcz5GVNsIplUgFNTsH/bj6c0/otuv6OA+7d1j04ds88S59Yxde0yCkmARmL4bFPs/6T88P3HYbjy9qBLtq2G5Fq0VqDq9HlYbdbqBSYbjmZ+GqlTxidSVMicm6aj4NE67XOSISAtjQRDHe2xe91zDd3lGMAkXU7cdWbZbNNyiuQPVkbSIv4MXF+D/b2mFX/wWP/1dP3mpHr90P/8VffbLlUc/H3/8RljR81fJd//oF6/Ut3/Tb/5qfP3n4dM/jr58I/4Fo2352G6M1D0AAAAASUVORK5CYII=&amp;apos;); background-size: cover; display: block;&quot;&gt;
      &lt;img class=&quot;gatsby-resp-image-image&quot; style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot; alt=&quot;Doctor + Tensorflow&quot; title src=&quot;/static/5363fe52234b34b1cfb3df90823e9be8/8ce52/doctor-screenshot.png&quot; srcset=&quot;/static/5363fe52234b34b1cfb3df90823e9be8/6b2ea/doctor-screenshot.png 275w,
/static/5363fe52234b34b1cfb3df90823e9be8/dd45a/doctor-screenshot.png 550w,
/static/5363fe52234b34b1cfb3df90823e9be8/8ce52/doctor-screenshot.png 681w&quot; sizes=&quot;(max-width: 681px) 100vw, 681px&quot;&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    
&lt;figcaption&gt;
&lt;strong&gt;Final Result:&lt;/strong&gt; The Doctor detects an I/O issues by seeing there is a low CPU usage, even if there are spikes caused by V8.
&lt;/figcaption&gt;
&lt;/figure&gt;&lt;h2 id=&quot;contact&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#contact&quot; aria-label=&quot;contact permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Contact&lt;/h2&gt;&lt;p&gt;If you would like us to do a workshop, where we teach how to profile and improve the performance of your application. Or if you need Machine Learning applied to some of your data. Then, feel free to contact us at &lt;a href=&quot;https://www.nearform.com/contact/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.nearform.com/contact/&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[All the latest coverage and news on Clinic.js]]></title><description><![CDATA[We have been very remiss in keeping the Clinic.js blog up to date. Rest assured that is going to change for 2020. If you are curious about…]]></description><link>https://clinicjs.org/blog/all-the-latest-coverage-and-news-on-clinic-js/</link><guid isPermaLink="false">https://clinicjs.org/blog/all-the-latest-coverage-and-news-on-clinic-js/</guid><dc:creator><![CDATA[Conor O'Neill]]></dc:creator><content:encoded>&lt;p&gt;We have been very remiss in keeping the Clinic.js blog up to date. Rest assured that is going to change for 2020.&lt;/p&gt;
&lt;p&gt;If you are curious about how Clinic.js might be able to help you pinpoint performance bottlenecks, here’s a glimpse at how it has helped others and what they have to say about what makes it unique.&lt;/p&gt;
&lt;h2 id=&quot;nearform-research-new-team-members&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nearform-research-new-team-members&quot; aria-label=&quot;nearform research new team members permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;NearForm Research new team members&lt;/h2&gt;
&lt;p&gt;The most important thing to tell you is that NearForm Research, a new group inside NearForm, is now responsible for Clinic.js. It&apos;s still the same Node.js experts but now we have even more team members. You can expect to see a &lt;em&gt;lot&lt;/em&gt; of new functionality in Clinic.js over the next several months.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Our newly expanded NearForm Research team finally all together in one place! 🚀 &lt;a href=&quot;https://twitter.com/hashtag/ideasflowing?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#ideasflowing&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/opensource?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#opensource&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/nodejs?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#nodejs&lt;/a&gt; &lt;a href=&quot;https://twitter.com/jasnell?ref_src=twsrc%5Etfw&quot;&gt;@jasnell&lt;/a&gt; &lt;a href=&quot;https://twitter.com/addaleax?ref_src=twsrc%5Etfw&quot;&gt;@addaleax&lt;/a&gt; &lt;a href=&quot;https://twitter.com/goto_bus_stop?ref_src=twsrc%5Etfw&quot;&gt;@goto_bus_stop&lt;/a&gt; &lt;a href=&quot;https://t.co/Gub6LELzrF&quot;&gt;pic.twitter.com/Gub6LELzrF&lt;/a&gt;&lt;/p&gt;&amp;mdash; NearForm Research (@NF__Research) &lt;a href=&quot;https://twitter.com/NF__Research/status/1222486482939793408?ref_src=twsrc%5Etfw&quot;&gt;January 29, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;h2 id=&quot;getting-involved&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#getting-involved&quot; aria-label=&quot;getting involved permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Getting involved&lt;/h2&gt;
&lt;p&gt;We love hearing from Clinic.js users and how it helped to solve performance issues for them. If you are interested in sharing your thoughts on the future of Clinic.js, please get in touch.&lt;/p&gt;
&lt;h2 id=&quot;some-great-mentions-of-clinicjs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-great-mentions-of-clinicjs&quot; aria-label=&quot;some great mentions of clinicjs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some great mentions of Clinic.js&lt;/h2&gt;
&lt;h3 id=&quot;adp-lifion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#adp-lifion&quot; aria-label=&quot;adp lifion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ADP Lifion&lt;/h3&gt;
&lt;p&gt;Clinic.js is one of those tools that has become invaluable for many Node.js developers. We were particularly pleased to see this post from Ali Yousuf in  ADP Lifion Engineering on the &lt;a href=&quot;https://eng.lifion.com/promise-allpocalypse-cfb6741298a7&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Promise.allpocalypse&lt;/a&gt; - The performance implications of misunderstanding Node.js promises.&lt;/p&gt;

  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block;  max-width: 600px; margin-left: auto; margin-right: auto;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 62.54545454545455%; position: relative; bottom: 0; left: 0; background-image: url(&amp;apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsSAAALEgHS3X78AAABt0lEQVQoz4XS627aMBQHcD8H5ZLEie8JITdiQoGghBDaIcFgmrov+zgm7Yk67Vl3klCppZUq/XT0t33s2FJQEK+Em0pPQ+VqeoPdDGWi5xs9r+I0Hwf3qHp4WqwP+v5Lkj1Eun4t1jVMxrNdpHfJrAE5SDZhWnOV9voYcRXb1LecMSZvWI6Hicd4QJiPHY9Qn4qQiojw0KYTWB0YDBE2ESoSKhYyhspl1A2pCCzbhXMhSy9tuKlwpx3laRMrZDnKsMTI5COTtZUbbQVwtsMC+Ag0mFgaGNqY0bQ1dTAiiLIxJZ6NpYUVsV3iuI6toMIM7HeY3z7KsxwfE98m8IQxgJsPTY4EHQsReDL0ZaREwMWEi0DIUPKJiQU8njeTIHwJAYMGFZm2i7rrDQ02gmryJnTVgIvRYbv0XreK7vr4bmC/0bd7rdf5atAF3Gt3IeFqKpOGSK5BJkw2v8fHXM29rKFSVO9/FvVTufuRV98XxXlZflsW5yw/ZqvjbHX4QP41W58AZFTW52JzLKtTuT2ti8My3y/y/Xz5CNLZdqqrG4nevKjQ459/28vz5tdzBS5X28vfxu9P/AeiDZ3MgnTgDAAAAABJRU5ErkJggg==&amp;apos;); background-size: cover; display: block;&quot;&gt;
      &lt;img class=&quot;gatsby-resp-image-image&quot; style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot; alt=&quot;ADP Doctor&quot; title src=&quot;/static/b71b36956e00205c29591f70a2025e3d/0a47e/doctor_adp.png&quot; srcset=&quot;/static/b71b36956e00205c29591f70a2025e3d/6b2ea/doctor_adp.png 275w,
/static/b71b36956e00205c29591f70a2025e3d/dd45a/doctor_adp.png 550w,
/static/b71b36956e00205c29591f70a2025e3d/0a47e/doctor_adp.png 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot;&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
&lt;h3 id=&quot;opensourcecom&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#opensourcecom&quot; aria-label=&quot;opensourcecom permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Opensource.com&lt;/h3&gt;
&lt;p&gt;This was quickly followed by Hiren Dhadhuk over on opensource.com including Clinic.js in their &lt;a href=&quot;https://opensource.com/article/20/1/open-source-tools-nodejs&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;9 favorite open source tools for Node.js developers&lt;/a&gt;&lt;/p&gt;

  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block;  max-width: 520px; margin-left: auto; margin-right: auto;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 55.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url(&amp;apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAAC3klEQVQoz1WT3UvTYRTH9xd0EVQEWrnU1Mre08qJjaltuq3ptFJzOkvLgopKR6+oWOFQc7a17bc3l2YmqenUqVBWvuFFb9SFEAhRhARFV11++m2zoIsDzzmc53O+5znnkWg2uVCLpklwo453kbMxdF42MX5kVwfXTvbRcK6fkgMdZG9whOP/TLwXtmVfEgmKoFgB3RY3hgxfGBoqopIKFOyxU3/Jx/PJl0xNzXPNOIgyxok2MQLKjY/k/RUhiSgTOJzo5aFngtP5DvJ3OMnf5qZC3k1dVYD0VW04LQN8XVpk6fs3HjlnRAFOcuNc4TyjIiIi5IeBSqkTY0Y3b9+94279U7p9YxxNFfBbXvHkwTT5ey202wRqT3h5Pj6P+Uo/iigbeVt89HY+o1rvQL/TwbEUbwjoCsvO2+phduotnz5/xO8Y5bjMg/feGJnSVmYLjnO/qIY9K62o4ltRJ1rFtgUMsi5RxHvs5mF6HoxTleNHcjjJTVa0g+uVfQSGgxiV7aSvNuMyj1Gu7aIu2cRPQzaFsbcpOtDDgH+GppoAmVHi0yR7mH7xhoXFD/jtI2IxG5LQMAq2ewkGJ7lcaSN1hYULpUNYGgfJjmrjS5EWZ+YZUlfdx3vnGZNzrzHf6EO+xk7dmQEGh0Y4lt6KYl1reEskoUr3GoN0dfYil7ZTtrmN4K1GNPs7EPaf43Oxin0xLsyp1/ndYuLN035OiABdso/x8UkulFuRr7WhS/JFpmyUd4ZbLc+1oIgWmNMZGM4p5WhCM79KlZhSTDSlN7BQXMi0WseHwjy00U1Y70zg73hMlvQu2gSvCBMie1iS5uZUQTMZ4qTbZSaoPkhpshmr7CIvtHrO777NQpEedVwD9Wl1BFRV6GXdBMRWy1RtHNogiDu5/DlCwNA+Za63k5fg4IdBw4jGIMLdHElqQbGxhVHNWa6m1LIzuger/CYDymo0u31UaJtQxVlFZZ7/fs0f/isFUAXK6R4AAAAASUVORK5CYII=&amp;apos;); background-size: cover; display: block;&quot;&gt;
      &lt;img class=&quot;gatsby-resp-image-image&quot; style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot; alt=&quot;Opensource.com Clinic.js&quot; title src=&quot;/static/6fa343594070b636aacc5fa1e6555c30/69902/tools_hardware_purple.png&quot; srcset=&quot;/static/6fa343594070b636aacc5fa1e6555c30/6b2ea/tools_hardware_purple.png 275w,
/static/6fa343594070b636aacc5fa1e6555c30/69902/tools_hardware_purple.png 520w&quot; sizes=&quot;(max-width: 520px) 100vw, 520px&quot;&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
&lt;h3 id=&quot;sematext&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sematext&quot; aria-label=&quot;sematext permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sematext&lt;/h3&gt;
&lt;p&gt;And earlier in 2019, Adnan Rahić included Clinic.js in their &lt;a href=&quot;https://sematext.com/blog/nodejs-open-source-monitoring-tools/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Node.js Open Source Monitoring Tools&lt;/a&gt; list. And we loved the comment that &quot;It’s surprisingly easy to use.&quot;&lt;/p&gt;

  &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block;  max-width: 600px; margin-left: auto; margin-right: auto;&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 54.90909090909091%; position: relative; bottom: 0; left: 0; background-image: url(&amp;apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAgP/2gAMAwEAAhADEAAAAXRkNYkIP//EABoQAAEFAQAAAAAAAAAAAAAAAAMAAQQREyD/2gAIAQEAAQUCeLSMHLn/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGn/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AYV//8QAGhABAAEFAAAAAAAAAAAAAAAAAQARICEyUf/aAAgBAQAGPwLYYZGvLf/EABwQAAEEAwEAAAAAAAAAAAAAAAEAEBEhUZHB4f/aAAgBAQABPyHig9YORlTUVpibX//aAAwDAQACAAMAAAAQ4D//xAAXEQADAQAAAAAAAAAAAAAAAAAAARFR/9oACAEDAQE/EIwqR//EABcRAAMBAAAAAAAAAAAAAAAAAAABEWH/2gAIAQIBAT8Q0I2f/8QAHRAAAgEEAwAAAAAAAAAAAAAAAAERITFBYVFxof/aAAgBAQABPxBzpKyqDdRGSjUsVFXhwIdBOLDsj//Z&amp;apos;); background-size: cover; display: block;&quot;&gt;
      &lt;img class=&quot;gatsby-resp-image-image&quot; style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot; alt=&quot;Sematext Clinic.js&quot; title src=&quot;/static/2a66d12ababe95a11e5aee1f9608ce28/b4294/sematext.jpg&quot; srcset=&quot;/static/2a66d12ababe95a11e5aee1f9608ce28/35f54/sematext.jpg 275w,
/static/2a66d12ababe95a11e5aee1f9608ce28/d7854/sematext.jpg 550w,
/static/2a66d12ababe95a11e5aee1f9608ce28/b4294/sematext.jpg 600w&quot; sizes=&quot;(max-width: 600px) 100vw, 600px&quot;&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
&lt;h2 id=&quot;tensorflowjs-in-clinicjs-doctor&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tensorflowjs-in-clinicjs-doctor&quot; aria-label=&quot;tensorflowjs in clinicjs doctor permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TensorFlow.js in Clinic.js Doctor&lt;/h2&gt;
&lt;p&gt;The TensorFlow.js team have very kindly highlighted its use in Clinic.js Doctor at multiple events including TensorFlow Dev and Node+JS Interactive.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 52.16844751728472%; position: relative; height: 0; overflow: hidden; &quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/L5jWvv0QTOs?list=PLfMzBWSH11xZPfWcC0DqFqKo_reMP58mw&amp;amp;t=1978&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2 id=&quot;clinicjs-helping-users&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#clinicjs-helping-users&quot; aria-label=&quot;clinicjs helping users permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Clinic.js Helping Users&lt;/h2&gt;
&lt;p&gt;Here&apos;s just a selection of the lovely things people have been saying on Twitter about how Clinic.js has helped them.&lt;/p&gt;
&lt;h3 id=&quot;michael-geers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#michael-geers&quot; aria-label=&quot;michael geers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Michael Geers&lt;/h3&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Was able to cut the build time of our design system in half today 🚀. First time I used clinic.js by &lt;a href=&quot;https://twitter.com/NearForm?ref_src=twsrc%5Etfw&quot;&gt;@NearForm&lt;/a&gt;. Awesome tool to visualise what&amp;#39;s going on inside your node process. Thanks &lt;a href=&quot;https://twitter.com/DennisReimann?ref_src=twsrc%5Etfw&quot;&gt;@DennisReimann&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/uiengine?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#uiengine&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/designsystem?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#designsystem&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/profiling?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#profiling&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/debugging?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#debugging&lt;/a&gt;&lt;a href=&quot;https://t.co/88xCDuec06&quot;&gt;https://t.co/88xCDuec06&lt;/a&gt; &lt;a href=&quot;https://t.co/vNJDlkdK8M&quot;&gt;pic.twitter.com/vNJDlkdK8M&lt;/a&gt;&lt;/p&gt;&amp;mdash; Michael Geers (@naltatis) &lt;a href=&quot;https://twitter.com/naltatis/status/1159463320711258112?ref_src=twsrc%5Etfw&quot;&gt;August 8, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;h3 id=&quot;liran-tal&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#liran-tal&quot; aria-label=&quot;liran tal permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Liran Tal&lt;/h3&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;/3 Through these questions we understood the left and right borders and usage scenarios. One of the preliminary activities to developing this was doing performance testing with &lt;a href=&quot;https://twitter.com/NearForm?ref_src=twsrc%5Etfw&quot;&gt;@NearForm&lt;/a&gt;&amp;#39;s clinic to assess the JSON processing impact on the CPU&lt;/p&gt;&amp;mdash; Liran Tal ✨ Node.js CLI Magic ✨ (@liran_tal) &lt;a href=&quot;https://twitter.com/liran_tal/status/1226810054407487488?ref_src=twsrc%5Etfw&quot;&gt;February 10, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;h3 id=&quot;antoine-gomez&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#antoine-gomez&quot; aria-label=&quot;antoine gomez permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Antoine Gomez&lt;/h3&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Thanks to &lt;a href=&quot;https://twitter.com/nodeclinic?ref_src=twsrc%5Etfw&quot;&gt;@nodeclinic&lt;/a&gt; for helping me figure out a stupid pagination memory bug in my code&lt;br&gt;&lt;br&gt;Before / After : &lt;a href=&quot;https://t.co/5kz7ebxad7&quot;&gt;pic.twitter.com/5kz7ebxad7&lt;/a&gt;&lt;/p&gt;&amp;mdash; Antoine Gomez (@antoineg) &lt;a href=&quot;https://twitter.com/antoineg/status/1172077196241985536?ref_src=twsrc%5Etfw&quot;&gt;September 12, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;h3 id=&quot;dipro-chatterjee&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dipro-chatterjee&quot; aria-label=&quot;dipro chatterjee permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dipro Chatterjee&lt;/h3&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;I recently spoke about &lt;a href=&quot;https://twitter.com/hashtag/clinicjs?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#clinicjs&lt;/a&gt; and is absolutely delighted to be a user.&lt;/p&gt;&amp;mdash; Dipro Chatterjee (@chatterjeedipro) &lt;a href=&quot;https://twitter.com/chatterjeedipro/status/1206867628482080768?ref_src=twsrc%5Etfw&quot;&gt;December 17, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;h3 id=&quot;flavio-aandres&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#flavio-aandres&quot; aria-label=&quot;flavio aandres permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Flavio Aandres&lt;/h3&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;es&quot; dir=&quot;ltr&quot;&gt;Estan usando Node.JS para aplicaciones realmente robustas, posiblemente con Leaks de memoria, Fallas en el EventLoop y procesos demasiado costosos?&lt;br&gt;&lt;br&gt;Clinic.JS permite saber visualmente cuales son las funciones o metodos que bloquean el eventLoop! 🔥🙌&lt;a href=&quot;https://t.co/7CDbA5mMwV&quot;&gt;https://t.co/7CDbA5mMwV&lt;/a&gt;&lt;/p&gt;&amp;mdash; Flavio Aandres (@FlavioAandres) &lt;a href=&quot;https://twitter.com/FlavioAandres/status/1196858806317338624?ref_src=twsrc%5Etfw&quot;&gt;November 19, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;h2 id=&quot;webinars&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#webinars&quot; aria-label=&quot;webinars permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Webinars&lt;/h2&gt;
&lt;p&gt;Want to find out more? We&apos;re planning a series of webinars to demonstrate how the Clinic.js suite of tools can help to solve Node.js performance issues. &lt;a href=&quot;https://community.nearform.com/clinic.js-webinar-registration&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Register your interest here&lt;/a&gt; and we&apos;ll be in touch with some suggested dates.&lt;/p&gt;</content:encoded></item></channel></rss>