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

[TSServer] Very slow semantic diagnostics and completion (7s) #53609

Closed
jeengbe opened this issue Mar 31, 2023 · 6 comments
Closed

[TSServer] Very slow semantic diagnostics and completion (7s) #53609

jeengbe opened this issue Mar 31, 2023 · 6 comments
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status.

Comments

@jeengbe
Copy link

jeengbe commented Mar 31, 2023

Bug Report

🔎 Search Terms

tsserver semantic diagnostic very slow

🕗 Version & Regression Information

With VSCode:

Version: 1.77.0 (user setup)
Commit: 7f329fe6c66b0f86ae1574c2911b681ad5a45d63
Date: 2023-03-29T10:02:16.981Z
Electron: 19.1.11
Chromium: 102.0.5005.196
Node.js: 16.14.2
V8: 10.2.154.26-electron.0
OS: Windows_NT x64 10.0.22621
Sandboxed: Yes

Running TS 5.0.2.

🙁 Problem

The language server is very slow in that changing a file results in semantic information seconds after the change, which is very painful to work with:
image
^ takes seconds to realize that requireLogin is a valid function.

Similarly, the following trace shows what happens in the seven seconds that pass between updateOpen and semanticDiag: https://gist.github.com/jeengbe/438eb0e7c772e7e715b03f34cfc15df9

What further information should I provide?

package.json:

{
  "name": "@dsh/frontend",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "dev": "concurrently \"pnpm:dev:*\"",
    "dev:translation-map": "nodemon -w tools -e ts --exec \"ts-node-transpile-only -r source-map-support/register tools/translation-map --watch\"",
    "dev:translate-app-dir": "nodemon -w tools -e ts --exec \"ts-node-transpile-only -r source-map-support/register tools/translate-app-dir --watch\"",
    "dev:next": "next dev",
    "build": "concurrently \"pnpm:build:*(!next|:watch)\" && pnpm run build:next",
    "build:next": "next build",
    "build:translation-map": "ts-node-transpile-only -r source-map-support/register tools/translation-map",
    "build:translate-app-dir": "ts-node-transpile-only -r source-map-support/register tools/translate-app-dir",
    "start": "next start",
    "lint": "eslint ."
  },
  "dependencies": {
    "@formatjs/icu-messageformat-parser": "2.3.0",
    "@isaacs/ttlcache": "1.2.2",
    "arangojs": "8.2.0",
    "intl-messageformat": "10.3.3",
    "ioredis": "5.3.1",
    "jsonwebtoken": "9.0.0",
    "next": "13.2.4",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "styled-components": "6.0.0-beta.13",
    "vality": "6.3.2",
    "vality-env": "1.0.0"
  },
  "devDependencies": {
    "@types/jsonwebtoken": "9.0.1",
    "@types/node": "18.15.11",
    "@types/react": "18.0.31",
    "@types/react-dom": "18.0.11",
    "@types/styled-components": "5.1.26",
    "@typescript-eslint/eslint-plugin": "5.57.0",
    "@typescript-eslint/parser": "5.57.0",
    "chokidar": "3.5.3",
    "csstype": "3.1.1",
    "eslint": "8.37.0",
    "eslint-config-next": "13.2.4",
    "eslint-config-prettier": "8.8.0",
    "eslint-plugin-jsx-a11y": "6.7.1",
    "eslint-plugin-prettier": "4.2.1",
    "nodemon": "2.0.22",
    "prettier": "2.8.7",
    "source-map-support": "0.5.21",
    "ts-node": "10.9.1",
    "typescript": "5.0.3",
    "yaml": "2.2.1"
  },
  "pnpm": {
    "peerDependencyRules": {
      "ignoreMissing": [
        "react-is"
      ]
    }
  }
}

tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "#/*": ["./src/*"]
    },
    "allowJs": true
  },
  "include": [
    "./src/**/*.ts",
    "./src/**/*.tsx",
    ".next/types/**/*.ts",
    "next-env.d.ts",
    "next.config.js"
  ],
  "exclude": ["**/node_modules/*", "**/__tests__/*",]
}

Full source code: https://github.com/DigitalerSchulhof/digitaler-schulhof/blob/e1ec5070e5b79dcc319216a8c1d03b09e6da3716/frontend/src/app/(schulhof)/%7Bpaths.schulhof%7D/%7Bpaths.schulhof.login%7D/page.tsx#L10

@DanielRosenwasser
Copy link
Member

Do you run into the same issues when you've disabled plugins?

Also, would you be able to provide more details on your build?

Specifically:

Also - we have a pretty lengthy page on diagnosing performance issues if you want to go in depth.

@jeengbe
Copy link
Author

jeengbe commented Apr 1, 2023

Hi, thanks for the answer!

I've removed the next plugin - sadly, without any noticeable difference.

tsc --noEmit --extendedDiagnostics runs as expected, so this is most likely an issue with the language server.

src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx:10:9 - error TS2552: Cannot find name 'requireLogina'. Did you mean 'requireLogin'?

10   await requireLogina(false);
           ~~~~~~~~~~~~~


Found 1 error in src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx:10

Files:                         641
Lines of Library:            29751
Lines of Definitions:       141132
Lines of TypeScript:          5283
Lines of JavaScript:            10
Lines of JSON:                  13
Lines of Other:                  0
Identifiers:                220401
Symbols:                    319789
Types:                       40331
Instantiations:             768354
Memory used:               362860K
Assignability cache size:   109337
Identity cache size:           296
Subtype cache size:           7804
Strict subtype cache size:       3
I/O Read time:               0.02s
Parse time:                  0.82s
ResolveModule time:          0.10s
ResolveTypeReference time:   0.02s
Program time:                1.05s
Bind time:                   0.34s
Check time:                  2.64s
transformTime time:          0.01s
commentTime time:            0.00s
printTime time:              0.03s
Emit time:                   0.03s
I/O Write time:              0.00s
Total time:                  4.06s```

I had already run the extension with tracing, however the result was rather underwhelming and didn't help me much.

Here's the output of running `analyze-trace`:
```log
Trace ended unexpectedly
> checkSourceFile: {"path":"/src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx"}

Hot Spots
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (3105ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (3008ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1260ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (803ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (803ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (786ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (783ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (3060ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2801ms)
│     ├─ Check expression from (line 22, char 10) to (line 22, char 17) (989ms)
│     │  └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (989ms)
│     │     └─ Check expression from (line 22, char 5) to (line 55, char 4) (949ms)
│     │        └─ Check expression from (line 25, char 12) to (line 54, char 6) (943ms)
│     └─ Check expression from (line 22, char 17) to (line 22, char 26) (949ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2998ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2850ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1138ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (767ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (767ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (753ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (747ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2981ms)
│  └─ Check deferred node from (line 22, char 8) to (line 24, char 18) (2816ms)
│     ├─ Check expression from (line 22, char 16) to (line 22, char 25) (1042ms)
│     └─ Check expression from (line 22, char 9) to (line 22, char 16) (769ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (769ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (753ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (749ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2908ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2810ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1095ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (773ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (773ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (758ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (754ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2898ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2808ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1102ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (780ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (780ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (765ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (762ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2894ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2803ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1096ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (771ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (771ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (757ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (753ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2900ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2774ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1037ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (853ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (853ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (831ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (827ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2874ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2779ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1094ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (766ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (766ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (747ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (744ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2864ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2769ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1069ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (761ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (761ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (743ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (740ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2873ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2713ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1053ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (774ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (774ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (757ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (753ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2854ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2770ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1077ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (777ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (777ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (758ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (755ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2837ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2744ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1077ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (753ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (753ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (736ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (732ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2844ms)
│  └─ Check deferred node from (line 22, char 9) to (line 24, char 19) (2750ms)
│     ├─ Check expression from (line 22, char 17) to (line 22, char 26) (1082ms)
│     └─ Check expression from (line 22, char 10) to (line 22, char 17) (759ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (759ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (744ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (741ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2831ms)
│  └─ Check deferred node from (line 22, char 8) to (line 24, char 18) (2753ms)
│     ├─ Check expression from (line 22, char 16) to (line 22, char 25) (1097ms)
│     └─ Check expression from (line 22, char 9) to (line 22, char 16) (755ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (755ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (734ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (731ms)
├─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (2749ms)
│  └─ Check deferred node from (line 22, char 8) to (line 24, char 18) (2650ms)
│     ├─ Check expression from (line 22, char 16) to (line 22, char 25) (1034ms)
│     └─ Check expression from (line 22, char 9) to (line 22, char 16) (735ms)
│        └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (735ms)
│           └─ Check expression from (line 22, char 5) to (line 55, char 4) (720ms)
│              └─ Check expression from (line 25, char 12) to (line 54, char 6) (716ms)
└─ Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx (1737ms)
   └─ Check expression from (line 22, char 10) to (line 22, char 17) (782ms)
      └─ Check expression in /src/ui/Heading/index.tsx from (line 14, char 24) to (line 56, char 2) (781ms)
         └─ Check expression from (line 22, char 5) to (line 55, char 4) (766ms)
            └─ Check expression from (line 25, char 12) to (line 54, char 6) (763ms)

No duplicate packages found

image

While it is already weird that Check file /src/app/(schulhof)/{paths.schulhof}/{paths.schulhof.login}/page.tsx takes several seconds, that still doesn't account for the 5s+ it takes to receive diagnostics.

Find the full semantic trace here: https://gist.github.com/jeengbe/52bdc7d1e8be653925d1f063875c8200

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Apr 7, 2023
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 5.1.0 milestone Apr 7, 2023
@jakebailey
Copy link
Member

I'm testing this out with both VS Code and tsc --watch running. If I add the letter "a" like you did (requireLogin -> requireLogina), they both take the same amount of time to issue the error, and removing the stray character to fix the code again takes the same amount of time to make the errors go away again.

Can you confirm? To me this doesn't seem like anything particularly related to tsserver.

I'll also note that on my machine, this takes 3 seconds and isn't particularly slow. Profiling shows there's some particularly expensive conditional type somewhere in your program, but, not sure where yet.

@sergei-dyshel
Copy link

FYI, there are numerous reports in vscode issue microsoft/vscode#178799 with similar symptoms, mostly during TS development but I personally observed this behavior (to lesser extent) with other languages so I think it's not directly related to TS language service but more about VScode extension host.

@jeengbe
Copy link
Author

jeengbe commented May 2, 2023

Hi @jakebailey,

apologies, I missed your comment and forgot about the thread. I can confirm that for me, the language server is quite a bit slower than tsc --watch. After upgrading to 5.1.0-dev.20230502, it feels like it's quite a bit faster now, but that might also merely be a fluke. tsc --watch, however, appears to be consistently faster than VS Code.

@sergei-dyshel, I believe this is not with VS Code directly, since with other (significantly larger) projects, I don't experience this issue.

Maybe this is related to vercel/next.js#48748 and the issue is that TypeScript possibly misses caching certain files? Without any real knowledge of what Next does under the hood, it seems to be compiling way too many (1000+) files on a single line changed.

Also, fwiw, it appears to not matter whether I use WSL or Windows directly.

@jeengbe
Copy link
Author

jeengbe commented Jun 10, 2023

I'm on 5.1.3 now and the issue is completely resolved. Updates are now checked as quickly as ever.

@jeengbe jeengbe closed this as completed Jun 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

5 participants