<p dir="auto">I'm currently debugging why a particular test suite takes 26s in Deno when it should be faster. Noticed that we spend about 55% of the time on the <code class="notranslate">realpath</code> syscall. The majority of those are coming from <code class="notranslate">ensure_registry_read_permission</code> which tends to trigger two <code class="notranslate">realpath</code> syscalls pretty frequently.</p>
<p dir="auto"></p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/denoland/deno/blob/d43e75cbb204e3537bd008e3b2a22d7de89a6f4c/cli/npm/resolvers/common.rs#L93-L120">deno/cli/npm/resolvers/common.rs</a>
    </p>
    <p class="mb-0 color-fg-muted">
        Lines 93 to 120
      in
      <a data-pjax="true" class="commit-tease-sha" href="/denoland/deno/commit/d43e75cbb204e3537bd008e3b2a22d7de89a6f4c">d43e75c</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L93" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="93"></td>
          <td id="LC93" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-k">pub</span> <span class="pl-k">fn</span> <span class="pl-en">ensure_registry_read_permission</span><span class="pl-kos">(</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L94" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="94"></td>
          <td id="LC94" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-s1">fs</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">Arc</span><span class="pl-kos">&lt;</span><span class="pl-k">dyn</span> <span class="pl-smi">FileSystem</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L95" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="95"></td>
          <td id="LC95" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-s1">permissions</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-k">dyn</span> <span class="pl-smi">NodePermissions</span><span class="pl-kos">,</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L96" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="96"></td>
          <td id="LC96" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-s1">registry_path</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">Path</span><span class="pl-kos">,</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L97" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="97"></td>
          <td id="LC97" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-s1">path</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">Path</span><span class="pl-kos">,</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L98" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="98"></td>
          <td id="LC98" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-kos">)</span> -&gt; <span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-smi">AnyError</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L99" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="99"></td>
          <td id="LC99" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-c">// allow reading if it's in the node_modules</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L100" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="100"></td>
          <td id="LC100" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-k">if</span> path<span class="pl-kos">.</span><span class="pl-en">starts_with</span><span class="pl-kos">(</span>registry_path<span class="pl-kos">)</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L101" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="101"></td>
          <td id="LC101" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     &amp;&amp; path </td>
        </tr>

        <tr class="border-0">
          <td id="L102" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="102"></td>
          <td id="LC102" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-kos">.</span><span class="pl-en">components</span><span class="pl-kos">(</span><span class="pl-kos">)</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L103" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="103"></td>
          <td id="LC103" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-kos">.</span><span class="pl-en">all</span><span class="pl-kos">(</span>|c| !<span class="pl-en">matches</span><span class="pl-en">!</span><span class="pl-kos">(</span>c, std::path::<span class="pl-v">Component</span>::<span class="pl-v">ParentDir</span><span class="pl-kos">)</span><span class="pl-kos">)</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L104" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="104"></td>
          <td id="LC104" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L105" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="105"></td>
          <td id="LC105" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-c">// todo(dsherret): cache this?</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L106" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="106"></td>
          <td id="LC106" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-k">if</span> <span class="pl-k">let</span> <span class="pl-v">Ok</span><span class="pl-kos">(</span>registry_path<span class="pl-kos">)</span> = fs<span class="pl-kos">.</span><span class="pl-en">realpath_sync</span><span class="pl-kos">(</span>registry_path<span class="pl-kos">)</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L107" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="107"></td>
          <td id="LC107" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-k">match</span> fs<span class="pl-kos">.</span><span class="pl-en">realpath_sync</span><span class="pl-kos">(</span>path<span class="pl-kos">)</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L108" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="108"></td>
          <td id="LC108" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-v">Ok</span><span class="pl-kos">(</span>path<span class="pl-kos">)</span> <span class="pl-k">if</span> path<span class="pl-kos">.</span><span class="pl-en">starts_with</span><span class="pl-kos">(</span>registry_path<span class="pl-kos">)</span> =&gt; <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L109" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="109"></td>
          <td id="LC109" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-k">return</span> <span class="pl-v">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L110" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="110"></td>
          <td id="LC110" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L111" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="111"></td>
          <td id="LC111" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-v">Err</span><span class="pl-kos">(</span>e<span class="pl-kos">)</span> <span class="pl-k">if</span> e<span class="pl-kos">.</span><span class="pl-en">kind</span><span class="pl-kos">(</span><span class="pl-kos">)</span> == <span class="pl-smi">ErrorKind</span><span class="pl-kos">::</span><span class="pl-v">NotFound</span> =&gt; <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L112" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="112"></td>
          <td id="LC112" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-k">return</span> <span class="pl-v">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L113" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="113"></td>
          <td id="LC113" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L114" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="114"></td>
          <td id="LC114" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         _ =&gt; <span class="pl-kos">{</span><span class="pl-kos">}</span> <span class="pl-c">// ignore</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L115" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="115"></td>
          <td id="LC115" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L116" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="116"></td>
          <td id="LC116" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L117" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="117"></td>
          <td id="LC117" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L118" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="118"></td>
          <td id="LC118" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">  </td>
        </tr>

        <tr class="border-0">
          <td id="L119" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="119"></td>
          <td id="LC119" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   permissions<span class="pl-kos">.</span><span class="pl-en">check_read</span><span class="pl-kos">(</span>path<span class="pl-kos">)</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L120" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="120"></td>
          <td id="LC120" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-kos">}</span> </td>
        </tr>
    </tbody></table>
  </div>
</div>
<p></p>
<p dir="auto">In my case the <code class="notranslate">node_modules</code> branch inside the if-statement is hit about 100k times. The first <code class="notranslate">realpath</code> call checks the registry path which is always the exact same path for me. The second call against <code class="notranslate">path</code> has lots of duplicated checks too. Did a little analysis and here is a list of the top paths which are checked repeatedly.</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="7084 &quot;/project/node_modules/.deno/happy-dom@9.20.3/node_modules/happy-dom/package.json&quot;
4660 &quot;/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/package.json&quot;
2320 &quot;/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/icons/lib/cjs/generated-icons/20px/paths&quot;
2320 &quot;/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/icons/lib/cjs/generated-icons/16px/paths&quot;
1952 &quot;/project/node_modules/.deno/@testing-library+user-event@14.4.3/node_modules/@testing-library/user-event/dist/esm/package.json&quot;
1628 &quot;/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/package.json&quot;
1536 &quot;/project/node_modules/.deno/date-fns@2.30.0/node_modules/date-fns/package.json&quot;
 902 &quot;/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/lib/etc/roles/literal&quot;
 655 &quot;/project/node_modules/.deno/@testing-library+dom@9.3.0/node_modules/@testing-library/package.json&quot;
 491 &quot;/project/node_modules/.deno/date-fns@2.30.0/node_modules/date-fns/node_modules&quot;
 491 &quot;/project/node_modules/.deno/date-fns@2.30.0/node_modules/@babel/runtime/package.json&quot;
 429 &quot;/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/lib/etc/roles/dpub&quot;
 374 &quot;/project/node_modules/.deno/call-bind@1.0.2/node_modules/call-bind/package.json&quot;
 352 &quot;/project/node_modules/.deno/react@18.2.0/node_modules/react/package.json&quot;"><pre class="notranslate">7084 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/happy-dom@9.20.3/node_modules/happy-dom/package.json<span class="pl-pds">"</span></span>
4660 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/package.json<span class="pl-pds">"</span></span>
2320 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/icons/lib/cjs/generated-icons/20px/paths<span class="pl-pds">"</span></span>
2320 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/@blueprintjs+icons@4.16.0/node_modules/@blueprintjs/icons/lib/cjs/generated-icons/16px/paths<span class="pl-pds">"</span></span>
1952 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/@testing-library+user-event@14.4.3/node_modules/@testing-library/user-event/dist/esm/package.json<span class="pl-pds">"</span></span>
1628 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/package.json<span class="pl-pds">"</span></span>
1536 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/date-fns@2.30.0/node_modules/date-fns/package.json<span class="pl-pds">"</span></span>
 902 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/lib/etc/roles/literal<span class="pl-pds">"</span></span>
 655 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/@testing-library+dom@9.3.0/node_modules/@testing-library/package.json<span class="pl-pds">"</span></span>
 491 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/date-fns@2.30.0/node_modules/date-fns/node_modules<span class="pl-pds">"</span></span>
 491 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/date-fns@2.30.0/node_modules/@babel/runtime/package.json<span class="pl-pds">"</span></span>
 429 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/aria-query@5.1.3/node_modules/aria-query/lib/etc/roles/dpub<span class="pl-pds">"</span></span>
 374 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/call-bind@1.0.2/node_modules/call-bind/package.json<span class="pl-pds">"</span></span>
 352 <span class="pl-s"><span class="pl-pds">"</span>/project/node_modules/.deno/react@18.2.0/node_modules/react/package.json<span class="pl-pds">"</span></span></pre></div>
<p dir="auto">Commenting out the <code class="notranslate">realpath</code> calls inside <code class="notranslate">ensure_registry_read_permission</code> brings down the total test time from 26s to 16s. This leads me to conclude that caching that is very much worth it. There is an older comment by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/dsherret/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/dsherret">@dsherret</a> which hints at potential gains by caching that already.</p>
<a target="_blank" rel="noopener noreferrer" href="https://user-images.githubusercontent.com/1062408/241506668-2c42bc53-da97-44d1-b6e3-b4bd4d2161bf.png"><img width="1680" alt="Screenshot 2023-05-28 at 08 27 54" src="https://user-images.githubusercontent.com/1062408/241506668-2c42bc53-da97-44d1-b6e3-b4bd4d2161bf.png" style="max-width: 100%;"></a>
<p dir="auto">Please run the topmost context in async mode, or allow top level await, akin to</p>
<p dir="auto"><a href="https://bugs.chromium.org/p/v8/issues/detail?id=9344" rel="nofollow">https://bugs.chromium.org/p/v8/issues/detail?id=9344</a></p>