tsx icon indicating copy to clipboard operation
tsx copied to clipboard

`node:assert`'s `assert.ok(false)` is really slow when using tsx

Open alcuadrado opened this issue 1 year ago • 6 comments
trafficstars

Acknowledgements

  • [X] I read the documentation and searched existing issues to avoid duplicates
  • [X] I understand this is a place to report a confirmed bug (not seek debugging help)
  • [X] I understand this is a collaborative open source project, and relies on community contributions
  • [X] I have read and understood the Contribution guide

Minimal reproduction

(sorry it's inline)

import assert from "node:assert/strict";

// An assert.ok(false) in a nested function with a ton of text (either code or comments) gets really slow.
// The more nested the function is, the slower it is.
// It doesn't happen with assert.equal(true, false), nor assert.ok(false, "message")

function f1() {
  function f2() {
    function f3() {
      function f4() {
        function f5() {
          function f6() {
            function f7() {
              function f8() {
                function f9() {
                  function f10() {
                    function f11() {
                      function f12() {
                        function f13() {
                          function f14() {
                            function f15() {
                              // Tons of commented out lines
                              //
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A
                              // A

                              assert.ok(false);
                            }
                            f15();
                          }
                          f14();
                        }
                        f13();
                      }
                      f12();
                    }
                    f11();
                  }
                  f10();
                }
                f9();
              }
              f8();
            }
            f7();
          }
          f6();
        }
        f5();
      }
      f4();
    }
    f3();
  }
  f2();
}
f1();

Version

4.9.6

Node.js version

22.0.0

Package manager

pnpm

Operating system

Linux

Problem & expected behavior (under 200 words)

  • What happened

When running node:assert's assert.ok(false) with tsx the automatic error message generation becomes notoriously slow.

It seems to get slower the larger the file is, and the deeper the function that call's assert.ok is.

I only tested this with an ESM package, running node --import tsx/esm repro.ts.

It is not slow if I compile the file and run it without tsx.

I have a strong belief that tsx is interfering with this function, making it really slow. As providing an error message to assert.ok works around the performance issue.

  • What I expected

It should be approximately as fast as the compiled version.

  • Error stack trace

No relevant stack traces.

  • Documentation links

No relevant documentation links.

  • Screenshots

No relevant screenshots.

  • Other

Thanks for creating and maintaining this project.

Contributions

  • [ ] I'm interested in working on this issue
  • [ ] I'm willing to offer financial support

alcuadrado avatar May 07 '24 19:05 alcuadrado

I may be able to help debug and/or fix this issue, as I'm quite familiar with Node's and v8's stack traces APIs, but I'm not familiar at all with tsx's internals.

alcuadrado avatar May 07 '24 19:05 alcuadrado

I can confirm that the error is also present in v4.0.0 and other versions of node.

alcuadrado avatar May 07 '24 19:05 alcuadrado

Thanks for the issue!

Would you mind moving the reproduction into a repo that compares the speed between tsx and node using hyperfine or even just time? Curious what you mean by "slow".

privatenumber avatar May 08 '24 02:05 privatenumber

Here's the reproduction: https://github.com/alcuadrado/tsx-slow-assert-failure

It runs it on github actions so that you don't need to install it.

In this case, it runs 150 times slower, but we discovered this because of a real-life assert.ok(expression) taking about 30 seconds when the test was originally passing (before expression turned falsy) in ~4ms.

alcuadrado avatar May 08 '24 16:05 alcuadrado

I boiled down the minimal reproduction further in https://github.com/privatenumber/node-bug-slow and reported it to Node.js: https://github.com/nodejs/node/issues/52962

privatenumber avatar May 12 '24 14:05 privatenumber

has someone encountered assert errors being swallowed?

joshxyzhimself avatar Aug 18 '24 00:08 joshxyzhimself