Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance: long print time in stylish formatter's text-table for long report strings #18709

Open
JoshuaKGoldberg opened this issue Jul 22, 2024 · 5 comments
Assignees
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion core Relates to ESLint's core APIs and features

Comments

@JoshuaKGoldberg
Copy link
Contributor

JoshuaKGoldberg commented Jul 22, 2024

When running npx eslint on a repository with many errors containing long descriptions and rule names, the stylish formatter can take a surprisingly long time to print results. @johnsoncodehk and I discovered this on https://github.com/johnsoncodehk/core/tree/d47d660758485c04dc26948b6ee9a42ac51a50df: more than half the command's time is spent in printResults!

The problem is a very slow /\s+$/ regex inside text-table on line 53. That regex is meant to remove all trailing whitespace in the string... which is now what String.prototype.trimEnd does.

The following fix inside text-table reduces the stylish formatter's runtime to near-zero:

        return map(row, function (c, ix) {
            // ...
-        }).join(hsep).replace(/\s+$/, '');
+        }).join(hsep).trimEnd();
    }).join('\n');

Single example time node node_modules/eslint/bin/eslint.js measurements on my M1 Max Mac Studio, with screenshots of the equivalent attached node --cpu-prof traces:

Measurement time Trace
Baseline 17.35s Performance trace showing over half the time in a printResults call
Fixed 8.70s Performance trace showing almost no time in a printResults call
Here is one of the strings being trimmed...
'   972  5   \x1B[33mwarning\x1B[39m  Unexpected nullable string value in conditional. Please handle the nullish/empty cases explicitly                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \x1B[2m@typescript-eslint/strict-boolean-expressions\x1B[22m   '

The stylish formatter calls to text-table here:

output += `${table(

Coincidentally, #18618 was filed last month to suggest replacing the not-updated-for-11-years text-table dependency. It was closed for lack of motivation. @jonkoops, I imagine this issue might help you feel vindicated a bit? 😄

I went ahead and published a text-table-fast package that has roughly the same API as text-table, but without the quadratic regular expression or support for the '.' alignment (which ESLint doesn't use).

Alternately, per #18618 (comment), maybe it'd make sense to extract the useful bits of text-table into stylish itself, and get rid of some overhead?

Co-authored-by: @johnsoncodehk

@nzakas
Copy link
Member

nzakas commented Jul 22, 2024

I'd be in favor of extracting the relevant logic directly into the stylish formatter.

@nzakas nzakas added accepted There is consensus among the team that this change meets the criteria for inclusion core Relates to ESLint's core APIs and features labels Jul 22, 2024
@jonkoops
Copy link

Captain Holt from the TV show Brooklyn 99 screaming "Vindication!"

But in all seriousness, great performance optimization 🏎️

@jonkoops
Copy link

Got something in the works to resolve this issue, @nzakas could you assign this one to me?

@JoshuaKGoldberg JoshuaKGoldberg self-assigned this Jul 25, 2024
@JoshuaKGoldberg
Copy link
Contributor Author

JoshuaKGoldberg commented Jul 25, 2024

GitHub makes it hard to assign issues to external contributors. I'll assign to myself to hold the issue but let you send a PR @jonkoops. All you! 🙂

@nzakas
Copy link
Member

nzakas commented Jul 25, 2024

@jonkoops assigned.

@JoshuaKGoldberg as long as someone has commented on the issue, you can assign it to them. :)

jonkoops added a commit to jonkoops/eslint that referenced this issue Jul 26, 2024
jonkoops added a commit to jonkoops/eslint that referenced this issue Jul 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion core Relates to ESLint's core APIs and features
Projects
Status: Ready to Implement
Development

No branches or pull requests

3 participants