denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.46k stars 5.37k forks source link

lsp: Autocompletion and error highlighting too slow while working with some files in VSCode #13404

Open sirikon opened 2 years ago

sirikon commented 2 years ago

Working on some files in VSCode using Deno plugin turns really slow on some scenarios. Overall, almost all files become slow to work on, but some are way slower than others. Seems like importing some external dependency worsens the problem.

I have other projects in Deno, and none of them have this behavior. Maybe the only difference is the amount of dependencies, but anyway, doesn't explain completely the slowness for me, seems like too much.

Here's a video to show how slow it can become, working on the following folder: https://github.com/sirikon/bilbostack-app/tree/2ddb90f4cb7c7392b2083858f0b585f1fcc04f26/back opening file src/web/server.ts.

https://user-images.githubusercontent.com/1157382/149842369-aae47ab5-a312-48d8-9d7b-ee462746477d.mp4

Here is the output that can be shown below when enabled using "deno.internalDebug": true: Download

deno --version

deno 1.17.3 (release, x86_64-unknown-linux-gnu)
v8 9.7.106.15
typescript 4.5.2

VSCode deno plugin: v3.10.1 VSCodium (It's just VSCode without Microsoft telemetry):

Version: 1.63.2
Commit: 899d46d82c4c95423fb7e10e68eba52050e30ba3
Date: 2021-12-17T00:20:01.675Z
Electron: 13.5.2
Chromium: 91.0.4472.164
Node.js: 14.16.0
V8: 9.1.269.39-electron.0
OS: Linux x64 5.10.0-10-amd64

Running on Debian 11 Bullseye

kitsonk commented 2 years ago

Turning on "deno.internalDebug" is certainly going to make things slower.

What is more useful is when things are getting slow, select Deno: Language Server Status and provide the output from that.

sirikon commented 2 years ago

@kitsonk Did the exact same thing as the video, almost the same slowness (90% maybe).

Here is the output:

Deno Language Server Status

Workspace Settings

{
  "enable": true,
  "cache": null,
  "config": "./deno.json",
  "importMap": "./src/import_map.json",
  "codeLens": {
    "implementations": false,
    "references": false,
    "referencesAllFunctions": false,
    "test": true
  },
  "internalDebug": false,
  "lint": true,
  "suggest": {
    "completeFunctionCalls": false,
    "names": true,
    "paths": true,
    "autoImports": true,
    "imports": {
      "autoDiscover": true,
      "hosts": {
        "https://deno.land": true,
        "https://x.nest.land": true,
        "https://crux.land": true
      }
    }
  },
  "unstable": true
}

Workspace Details

Performance

Name Duration Count
code_action 168ms 1
code_lens 0ms 1
document_symbol 0ms 1
get_navigation_tree 0ms 2
op_exists 0ms 812
op_script_version 0ms 177
request 710ms 2
update_diagnostics 1252ms 1
update_diagnostics_deps 2ms 1
update_diagnostics_lint 2ms 1
update_diagnostics_ts 1252ms 1
sirikon commented 2 years ago

Another output: Same operation, but being the first thing done in the editor after opening it (No opening/closing other tabs etc), maybe it makes a difference, I'm not sure:

Deno Language Server Status

Workspace Settings

{
  "enable": true,
  "cache": null,
  "config": "./deno.json",
  "importMap": "./src/import_map.json",
  "codeLens": {
    "implementations": false,
    "references": false,
    "referencesAllFunctions": false,
    "test": true
  },
  "internalDebug": false,
  "lint": true,
  "suggest": {
    "completeFunctionCalls": false,
    "names": true,
    "paths": true,
    "autoImports": true,
    "imports": {
      "autoDiscover": true,
      "hosts": {
        "https://x.nest.land": true,
        "https://deno.land": true,
        "https://crux.land": true
      }
    }
  },
  "unstable": true
}

Workspace Details

Performance

Name Duration Count
code_action 652ms 2
code_lens 1ms 1
document_symbol 0ms 1
folding_range 2ms 1
get_navigation_tree 0ms 2
op_dispose 0ms 1
op_get_change_range 0ms 2
op_get_length 0ms 3
op_get_text 0ms 2
op_resolve 0ms 1
op_script_version 0ms 970
request 333ms 8
semantic_tokens_full 45ms 1
signature_help 1320ms 1
update_diagnostics 1289ms 1
update_diagnostics_deps 1ms 1
update_diagnostics_lint 1ms 1
update_diagnostics_ts 1289ms 1
kitsonk commented 2 years ago

177 documents in memory is quite a lot and the signature_help and the update_diagnostics are quite laggy... trying to address this isn't going to be straight forward, but I think we need to look at some optimisations, as both op_script_version and op_exists are getting called way more times than I would expect, and there were recent change in 4.5 that cause that.

Also, there is an import_map involved, which could mean that is adding another layer on top of it all of "complexity" that is causing it to perform slow.

sirikon commented 2 years ago

I'll gladly help in anything I can :slightly_smiling_face:

sirikon commented 2 years ago

Just discovered the origin of my problem within my project. Made a config builder that reads information from environment variables that kinda abused Typescript's type system, the mechanism seems to have really poor performance:

I was doing this: https://github.com/sirikon/bilbostack-app/blob/2ddb90f4cb7c7392b2083858f0b585f1fcc04f26/back/src/config/mod.ts#L6-L19 Using this: https://github.com/sirikon/denox/blob/e13ab86fd75f70435ab4a2183a663d5cfee8b7d9/config/environment.ts

Every key() call creates a new builder and passes the generic type making a concatenation of all the keys in a single object. Seems like LSP struggled hard with this script, today added a couple of new key() calls and it exploded, with the plugin saying that "computing the types was taking too long, maybe in an infinite loop" or something along the line.

Made a new implementation avoiding the cursed mecanism and all the performance problems vanished.

@kitsonk keep the issue open if you still consider that this scenario shouldn't happen, or close it if it was just my failure (Sorry for the noise!!!). As a suggestion, maybe displaying sooner some kind of notification like "this specific file/code block is taking too long to compute", before crashing, would be great in these scenarios, but that's up to you folks :heart: .

Anyway, thanks for your time :heart:

kitsonk commented 2 years ago

Thanks for following up!

maybe displaying sooner some kind of notification like "this specific file/code block is taking too long to compute"

That is the domain/feature of TypeScript type checker (tsc) which is embedded in Deno. It obviously uses internal information about how many types it is checking and how long that takes, where we can only "observe" and in that sense it is unlikely we will get it "correct", as it might be a slow machine or someone unavoidably has a large type system and they just suffer with it, so it is likely something we will continue to just let tsc "worry" about, while we focus on streamlining things around it.

You highlighted a couple of perf issues (though obviously they weren't the root cause of this issue) that we should address mentioned above, so will keep it open for that reason.

JaanJah commented 2 years ago

I also have the same issue, has anyone found a solution to this yet?

vxern commented 1 year ago

Are there any updates on this? Working with the Deno analyser/formatter/linter is extremely frustrating due to just how unbelievably slow it is, similar to what the author of this issue is experiencing, if not worse. I'd expect analysis to be instantaneous, meanwhile it currently takes ~2-3 seconds for anything to happen on-screen, often even longer. It's a real annoyance for development.

BlackGlory commented 11 months ago

177 documents in memory is quite a lot

I laughed when I saw this, my project has 1613 documents, maybe Deno is for small projects only? The slow response time of the LSP is the most frustrating issue I've encountered in Deno development. Now I just uninstall vscode_deno and pretend I'm developing a Node.js + TypeScript project.

joshpachner commented 11 months ago

Same. I love the concept of Deno and think it can really get adopted, but the actual DX has been killing me. Its so so slow.

Deno Language Server Status

Workspace Settings

{
  "enable": true,
  "disablePaths": [],
  "enablePaths": null,
  "cache": null,
  "cacheOnSave": false,
  "certificateStores": null,
  "config": null,
  "importMap": "./functions/import_map.json",
  "codeLens": {
    "implementations": true,
    "references": true,
    "referencesAllFunctions": true,
    "test": false
  },
  "internalDebug": false,
  "lint": true,
  "documentPreloadLimit": 1000,
  "suggest": {
    "imports": {
      "autoDiscover": true,
      "hosts": {
        "https://deno.land": true
      }
    }
  },
  "testing": {
    "args": [
      "--allow-all",
      "--no-check"
    ]
  },
  "tlsCertificate": null,
  "unsafelyIgnoreCertificateErrors": null,
  "unstable": false,
  "javascript": {
    "inlayHints": {
      "parameterNames": {
        "enabled": "none",
        "suppressWhenArgumentMatchesName": true
      },
      "parameterTypes": {
        "enabled": false
      },
      "variableTypes": {
        "enabled": false,
        "suppressWhenTypeMatchesName": true
      },
      "propertyDeclarationTypes": {
        "enabled": false
      },
      "functionLikeReturnTypes": {
        "enabled": false
      },
      "enumMemberValues": {
        "enabled": false
      }
    },
    "preferences": {
      "importModuleSpecifier": "shortest",
      "jsxAttributeCompletionStyle": "auto",
      "autoImportFileExcludePatterns": [],
      "useAliasesForRenames": true,
      "quoteStyle": "auto"
    },
    "suggest": {
      "completeFunctionCalls": false,
      "includeAutomaticOptionalChainCompletions": true,
      "includeCompletionsForImportStatements": true,
      "names": true,
      "paths": true,
      "autoImports": true,
      "enabled": true,
      "classMemberSnippets": {
        "enabled": true
      },
      "objectLiteralMethodSnippets": {
        "enabled": true
      }
    },
    "updateImportsOnFileMove": {
      "enabled": "prompt"
    }
  },
  "typescript": {
    "inlayHints": {
      "parameterNames": {
        "enabled": "none",
        "suppressWhenArgumentMatchesName": true
      },
      "parameterTypes": {
        "enabled": false
      },
      "variableTypes": {
        "enabled": false,
        "suppressWhenTypeMatchesName": true
      },
      "propertyDeclarationTypes": {
        "enabled": false
      },
      "functionLikeReturnTypes": {
        "enabled": false
      },
      "enumMemberValues": {
        "enabled": false
      }
    },
    "preferences": {
      "importModuleSpecifier": "shortest",
      "jsxAttributeCompletionStyle": "auto",
      "autoImportFileExcludePatterns": [],
      "useAliasesForRenames": true,
      "quoteStyle": "auto"
    },
    "suggest": {
      "completeFunctionCalls": false,
      "includeAutomaticOptionalChainCompletions": true,
      "includeCompletionsForImportStatements": true,
      "names": true,
      "paths": true,
      "autoImports": true,
      "enabled": true,
      "classMemberSnippets": {
        "enabled": true
      },
      "objectLiteralMethodSnippets": {
        "enabled": true
      }
    },
    "updateImportsOnFileMove": {
      "enabled": "prompt"
    }
  }
}

Workspace Details

Performance

Name Duration Count
code_action 590ms 1
code_lens 4ms 1
did_change 9ms 28
did_change_configuration 22ms 1
did_change_watched_files 0ms 2
document_symbol 590ms 1
folding_range 589ms 1
get_navigation_tree 297ms 2
op_load 0ms 2899
op_resolve 0ms 4
request 323ms 6
testing_update 10ms 18
tsc $configure 0ms 1
tsc getApplicableRefactors 590ms 1
tsc getNavigationTree 297ms 2
tsc getOutliningSpans 589ms 1
update_cache 0ms 1
update_diagnostics_deps 118ms 5
update_diagnostics_lint 5ms 19
update_diagnostics_ts 609ms 2
update_import_map 0ms 1
update_registries 1ms 1
update_tsconfig 0ms 1
virtual_text_document 3ms 1
ry commented 11 months ago

@joshpachner what version of Deno are you at?

joshpachner commented 11 months ago

@ry deno 1.38.4 (release, x86_64-pc-windows-msvc) and Deno v3.29.0 vscode extension

cknight commented 11 months ago

@joshpachner try upgrading to the latest Deno, currently 1.38.5. It has a few additional LSP improvements. You can also try disabling the code lens, which for me brings big improvements in performance. To do so, add "editor.codeLens": false to your .vscode settings.json.

joshpachner commented 11 months ago

Hey @cknight I upgraded, and removed code lens. I noticed its marginally quicker. (Previously if i was typing "const variableName" i would get a red line saying " "c" not found" that wouldnt ever go away unless i did a VC Windows Reload. With the new update it actually does go away).

But whats still not working is there's no intelisense when it comes to auto imports.

Granted. I could just not have it configured properly....

Deno Language Server Status

Workspace Settings

{
  "enable": true,
  "disablePaths": [],
  "enablePaths": null,
  "cache": null,
  "cacheOnSave": false,
  "certificateStores": null,
  "config": null,
  "importMap": "./functions/import_map.json",
  "codeLens": {
    "implementations": false,
    "references": false,
    "referencesAllFunctions": false,
    "test": false
  },
  "internalDebug": false,
  "lint": true,
  "documentPreloadLimit": 1000,
  "suggest": {
    "imports": {
      "autoDiscover": true,
      "hosts": {
        "https://deno.land": true
      }
    }
  },
  "testing": {
    "args": [
      "--allow-all",
      "--no-check"
    ]
  },
  "tlsCertificate": null,
  "unsafelyIgnoreCertificateErrors": null,
  "unstable": false,
  "javascript": {
    "inlayHints": {
      "parameterNames": {
        "enabled": "none",
        "suppressWhenArgumentMatchesName": true
      },
      "parameterTypes": {
        "enabled": false
      },
      "variableTypes": {
        "enabled": false,
        "suppressWhenTypeMatchesName": true
      },
      "propertyDeclarationTypes": {
        "enabled": false
      },
      "functionLikeReturnTypes": {
        "enabled": false
      },
      "enumMemberValues": {
        "enabled": false
      }
    },
    "preferences": {
      "importModuleSpecifier": "shortest",
      "jsxAttributeCompletionStyle": "auto",
      "autoImportFileExcludePatterns": [],
      "useAliasesForRenames": true,
      "quoteStyle": "auto"
    },
    "suggest": {
      "completeFunctionCalls": false,
      "includeAutomaticOptionalChainCompletions": true,
      "includeCompletionsForImportStatements": true,
      "names": true,
      "paths": true,
      "autoImports": true,
      "enabled": true,
      "classMemberSnippets": {
        "enabled": true
      },
      "objectLiteralMethodSnippets": {
        "enabled": true
      }
    },
    "updateImportsOnFileMove": {
      "enabled": "prompt"
    }
  },
  "typescript": {
    "inlayHints": {
      "parameterNames": {
        "enabled": "none",
        "suppressWhenArgumentMatchesName": true
      },
      "parameterTypes": {
        "enabled": false
      },
      "variableTypes": {
        "enabled": false,
        "suppressWhenTypeMatchesName": true
      },
      "propertyDeclarationTypes": {
        "enabled": false
      },
      "functionLikeReturnTypes": {
        "enabled": false
      },
      "enumMemberValues": {
        "enabled": false
      }
    },
    "preferences": {
      "importModuleSpecifier": "shortest",
      "jsxAttributeCompletionStyle": "auto",
      "autoImportFileExcludePatterns": [],
      "useAliasesForRenames": true,
      "quoteStyle": "auto"
    },
    "suggest": {
      "completeFunctionCalls": false,
      "includeAutomaticOptionalChainCompletions": true,
      "includeCompletionsForImportStatements": true,
      "names": true,
      "paths": true,
      "autoImports": true,
      "enabled": true,
      "classMemberSnippets": {
        "enabled": true
      },
      "objectLiteralMethodSnippets": {
        "enabled": true
      }
    },
    "updateImportsOnFileMove": {
      "enabled": "prompt"
    }
  }
}

Workspace Details

Performance

Name Duration Count
lsp.cache 1465ms 1
lsp.code_action 398ms 27
lsp.code_lens 0ms 11
lsp.completion 5376ms 1
lsp.did_change 18ms 22
lsp.document_highlight 133ms 5
lsp.document_symbol 541ms 9
lsp.folding_range 452ms 9
lsp.get_navigation_tree 541ms 9
lsp.hover 255ms 10
lsp.semantic_tokens_full 1457ms 10
lsp.testing_update 1ms 23
lsp.update_diagnostics_deps 3ms 14
lsp.update_diagnostics_lint 19ms 14
lsp.update_diagnostics_ts 746ms 9
tsc.host.$getDiagnostics 577ms 11
tsc.host.$restart 1ms 1
tsc.host.getApplicableRefactors 101ms 30
tsc.host.getCodeFixesAtPosition 532ms 5
tsc.host.getCompletionsAtPosition 5372ms 1
tsc.host.getDocumentHighlights 80ms 5
tsc.host.getEncodedSemanticClassifications 555ms 10
tsc.host.getNavigationTree 2ms 9
tsc.host.getOutliningSpans 3ms 9
tsc.host.getQuickInfoAtPosition 89ms 10
tsc.op.op_load 0ms 100
tsc.op.op_resolve 0ms 2556
tsc.request.$restart 1ms 1
tsc.request.getApplicableRefactors 273ms 27
tsc.request.getCodeFixesAtPosition 560ms 7
tsc.request.getCompletionsAtPosition 5373ms 1
tsc.request.getDocumentHighlights 133ms 5
tsc.request.getEncodedSemanticClassifications 1457ms 10
tsc.request.getNavigationTree 541ms 9
tsc.request.getOutliningSpans 452ms 9
tsc.request.getQuickInfoAtPosition 255ms 10
marsian83 commented 2 weeks ago

are there any updates on this? The LSP is slow indeed, I too have noticed this initially thought it was my machine, but it's definitely got something to do with deno

Anyone figured out any workarounds for better performance?

fro-profesional commented 2 weeks ago

are there any updates on this?

The LSP is slow indeed, I too have noticed this

initially thought it was my machine, but it's definitely got something to do with deno

Anyone figured out any workarounds for better performance?

I haven't had any issues with latest version not sure when the change happend tho, Im using deno 2.0.3 right now