tj / n

Node version management
MIT License
18.77k stars 738 forks source link

Finding `engine` is pretty slow #807

Closed elibarzilay closed 6 days ago

elibarzilay commented 1 month ago

Since it uses node to find the version, and starting it is kind of slow.

If it's ok to use jq, I'll be happy to make a PR that uses it if it exists, or use node otherwise.

shadowspawn commented 1 month ago

From some experimentation, the slowest part is using semver to resolve a complex version expression. Are you seeing a progress line containing "resolving"?

Relatively slow with complex expression:

% time n lsr engine
       found : /Users/john/Documents/Sandpits/n/issues/807/package.json
        read : >=14.6 <19.0.0
   resolving : >=14.6 <19.0.0
18.20.4
n lsr engine  1.47s user 0.38s system 86% cpu 2.149 total

Relatively fast with simple expression that is recognised by n and processed directly:

% time n lsr engine
       found : /Users/john/Documents/Sandpits/n/issues/807/package.json
        read : >18.0.0
      target : current
22.5.1
n lsr engine  0.06s user 0.04s system 75% cpu 0.141 total

The block of code that contains that progress uses npx to execute semver to resolve the expression:

https://github.com/tj/n/blob/76d6b9870c619d9393ba5c2e3e35fdda171e9773/bin/n#L1112

elibarzilay commented 1 month ago

I'm talking about the simple case, where just starting node is much slower than starting jq. When a resolution is needed, there's obviously no good way to avoid going through the code.

For example, n which auto in the source directory takes an average 354ms, and with jq I get 169ms.

shadowspawn commented 1 month ago

For interest, what are you doing that you notice the slowness?

shadowspawn commented 1 month ago

If it's ok to use jq, I'll be happy to make a PR that uses it if it exists, or use node otherwise.

On the one hand, I don't particularly like checking for an optional tool. On the other hand, the engine support checks for node in the same way! I do like that would not need node installed for processing simple expressions if jq is available.

PR welcome, see how it goes. (And I would like jq version included in the doctor output.)

elibarzilay commented 1 month ago
  1. Slowness: just running node has a significant startup overhead, with using node like this, that overhead is (at least) duplicated, which is how I noticed it. (So, just through plain interactive use.)
  2. An advantage of jq -- besides being smaller + faster -- is that it is a popular choice for CI pipelines, and since it's simple I figured it's worth the minor improvement.
  3. In addition, node can be popular in some setups, but n is useful in installing it in the first place for setups that lack a builtin node. So my guess is that there's good chances that there's a fair number of cases that would be simplified.
elibarzilay commented 1 month ago

@shadowspawn Made the above PR.

Apologies, but I can't access my work machine at the moment, so I used the tweak that I did previously, with a bit of reshuffling to make it a proper PR. Hopefully I didn't make have any stupid typos.

shadowspawn commented 6 days ago

Released in v10.0.0

elibarzilay commented 6 days ago

Thanks!