microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.09k stars 12.37k forks source link

Type checking/VS Code slow when using MUI #34801

Closed jdoklovic closed 2 years ago

jdoklovic commented 4 years ago

TypeScript Version: 3.8.0-dev.20191029

Search Terms: mui, material-ui, typescript, slow

Example Project https://github.com/jdoklovic/mui-slowness

Expected behavior: Make a bad change to something in src/react/pages/Main.tsx autocomplete seems to be speedy, and error reporting should be too.

Actual behavior: Takes forever to see errors

Related Issues: #32085, #32229, #31817, #30908

Not exactly sure what's going on, but the error reporting in VS Code is super slow. I've made sure I'm using specific named imports, and I've even forked MUI and mad all of the internal code so the same and removed things like import from '..' but it didn't seem to help.

Here's the output from tsserver logs which doesn't seem to contain anything that jumps out at me. Also note, I'm using typescript-eslint with the VS Code ESLint extension, not tslint, but eslint seems to be pretty fast.

mui-slowness-tsserver.log

amcasey commented 4 years ago

First off, this bug report is just about perfect, so thanks for that! Second, skipLibCheck usually helps, but you've already got that. Anyone else reading this might want to give that a shot.

I'll look for possible improvements in both TS and the MUI type decls. Thanks!

jdoklovic commented 4 years ago

Thanks @amcasey. Let me know if you need any other data/log dumps or whatever. Also, I hsould mention that if I launch the app with webpack-dev-server --open --config webpack.react.webview.js the VS Code editor is still super slow to report errors, but if I make a change and save, the watch process/compilation is super fast and usually completes and reloads the browser before VS Code catches up. Not sure if that's useful info or not.

amcasey commented 4 years ago

The issue we usually see with responsiveness in MUI consumers is with the large number of icon types. In this case, however, it appears that MUI is using some complicated conditional types to provide sophisticated checking of API usage. I'm experimenting with both tweaking their types and improving compiler perf, but, so far, the solution isn't obvious.

zaguiini commented 4 years ago

It's not just errors... Any changes takes enormous time to be processed.

dcworldwide commented 4 years ago

I am in compilation hell. 300% CPU and my machine is bricked for 15 minutes.

"@material-ui/core": "^4.3.3",
"@material-ui/icons": "^4.2.1",
"@material-ui/pickers": "^3.2.4",
"@material-ui/styles": "^4.3.3",

"typescript": "^3.7.2",

Ravnurin commented 4 years ago

TSC is still incredibly, frustratingly slow for me in any files using MUI. Typically takes anywhere between 5 to 10 seconds from making a change to the type checking to finish and errors being flagged.

When I first open VSC and start the build process, it seems sometimes type checking is relatively fast (1-2 seconds), but becomes slower over time (eventually hitting 5-10 secs). Other times, however, it seems it's also the amount of MUI components used in the working file that impacts TSC speeds.

I remember about 5 months ago I found using specifically TypeScript version 3.3.4000 to actually resolve the slow TSC issues, whereas the following versions were all affected by this slowness. Not tested it since though.

AlCalzone commented 4 years ago

In a small project of mine, I've started to have a watch process with noEmit specifically for *.tsx files. This gives significantly faster feedback (4-5 seconds) if something broke than IntelliSense, which takes forever to update.

amcasey commented 4 years ago

Unfortunately, I have yet to find either a solution or a mitigation. I'm reluctant to push a totally new strategy onto the MUI type authors and finding a smaller change with the same effect is much more difficult. Obviously, you do have the option of not using @types/material-ui, but that will make completion a lot less useful and error detection a lot less thorough.

amcasey commented 4 years ago

@rrebase @Ravnurin @AlCalzone Having additional (ideally, small) repros would help with this one. Is your code shareable?

amcasey commented 4 years ago

I decided to start over with a clean version of @jdoklovic's repro and now I'm seeing a ~3 second delay on startup and then good responsiveness after that (there's a ~2 second lag for squiggles, but that's by design, so they don't flicker, etc). I'm on VS Code 1.40.2 and TS 2.8.0-dev.20191207. I'll try to figure out where those 3 seconds are going, but they're a lot less worrisome than the 12 seconds in the original report.

If people are still seeing longer delays, additional repros would be very helpful. Also, consider giving TS 3.7 a shot, since we made a bunch of perf fixes.

AlCalzone commented 4 years ago

Is your code shareable?

I can email you an archive with the repo in it if that is okay. It currently consists of about 23 TSX and 32 TS files that are relevant to the frontend where I'm seeing the delays. I'll see if I can reduce the size or at least give you some steps how to trigger the longer delays.

amcasey commented 4 years ago

@AlCalzone Sure. first.last@microsoft.com

Edit: Please let me know when you do this, since external mail with attached JS is pretty likely to be flagged by IT.

amcasey commented 4 years ago

I dug into the 3 second delay and, once again, signs point to And and IsEmptyInterface as the source of the slowdown (since they use complex conditional types that affect type inference). I previously made an attempt to simplify those types, but it had unexpected semantic ramifications and had to be reverted. I'll try again.

AlCalzone commented 4 years ago

@amcasey I hope I find some time later today (CET). I'll let you know here when I send the mail.

AlCalzone commented 4 years ago

@amcasey I sent you an email with the subject "Repro for MUI slowness (AlCalzone)"

QingqiShi commented 4 years ago

Unfortunately, I have yet to find either a solution or a mitigation. I'm reluctant to push a totally new strategy onto the MUI type authors and finding a smaller change with the same effect is much more difficult. Obviously, you do have the option of not using @types/material-ui, but that will make completion a lot less useful and error detection a lot less thorough.

Not sure if not using @types/material-ui is actually an option since material-ui has the types bundled with the package.

amcasey commented 4 years ago

@AlCalzone Thanks! Found it in my spam folder. :wink:

amcasey commented 4 years ago

@QingqiShi You're quite right. We're usually dealing with typings from DefinitelyTyped and I got mixed up.

AlCalzone commented 4 years ago

@amcasey I resent the mail with the extension changed to zip1 as suggested. If that doesn't work, let me know.

Ravnurin commented 4 years ago

@amcasey have you had a chance to look into the slowdown some more? I can appreciate it's probably one of those that'll take a fair bit of time to fix - If you need an additional sample repro let me know, happy to put something together.

QingqiShi commented 4 years ago

Here's something to try as a workaround if you have a beefy machine:

I haven't had the opportunity to test this more extensively so if it works please let everyone know :)

dcworldwide commented 4 years ago

My memory was already maxed, so that didn't help me unfortunately.

LonJonn commented 4 years ago

Same as me. I on a Macbook Pro 2017 (which should be capable enough) and having issues like extreme fan speeds and computer temps. Is there any update on this issue?

amcasey commented 4 years ago

I've identified the slow part of the code in the repro that I have and it's complicated enough that compiling slowly seems justifiable, so my next step will be to determine whether the type definitions can be simplified. If that turns out not to be possible, I'll look for ways to speed up handling of this particular class of complex types.

amcasey commented 4 years ago

I'm actively working on this, but the changes aren't aimed at any particular TS milestone.

senjacob commented 4 years ago

I'm actively working on this, but the changes aren't aimed at any particular TS milestone.

Hi @amcasey,

It seems to me that when the project introduce a generic typed interface, everything becomes dead slow.

I have declared IFoo<T> { prop1: T; prop2: any; prop3?: any }

Once I use

someMethod(): IFoo<MyType> {
    return { prop1: myTypeObj, prop2: someValue };
}

the whole project and autocomplete became too slow in VS Code.

Please check it is a valid clue for your work.

Typescript version: 3.6.4 VS Code version: 1.41.1

Workspace Extensions: (I think this is too many, but VS Code intellisense, auto-import etc. were responding so fast before I add the generic type in code)

Auto Close Tag v0.5.6 Auto Import v1.5.3 Code Spell Checker v1.7.22 Git Lens - Git supercharged v10.2.0 Intellisense for CSS class names in HTML v1.19.0 JS Refactor v2,20.5 Live Server c5.6.1 npm Intellisense v1.3.0 Paste JSON as Code v12.0.46 sort-imports v6.1.0 TSLint v1.2.3 TypeLens v1.9.3 Visual Studio IntelliCode v1.2.4 Visual Studio Keymap v0.2.0 vscode-icons v9.7.0

amcasey commented 4 years ago

@senjacob Thanks for the pointer! Do you have an example of some code that was affected by this? Generic types are incredibly widely used and it would be terrible to discover that they destroy performance across the board.

joeytwiddle commented 4 years ago

Not sure if related, but styled-components also suffered a slowdown between 3.3.0 and 3.4.0. https://github.com/microsoft/TypeScript/issues/30663

amcasey commented 4 years ago

Thanks, @joeytwiddle! I believe that was the same underlying issue (e.g. https://github.com/microsoft/TypeScript/issues/30819) and should have been addressed by the same fix.

senjacob commented 4 years ago

@senjacob Thanks for the pointer! Do you have an example of some code that was affected by this? Generic types are incredibly widely used and it would be terrible to discover that they destroy performance across the board.

@amcasey Thanks for quick reply!

The codebase is private under NDA. Anyway, the finding about generic usage was wrong. Sorry if investigating on it took your valuable time. :(

Disabling TypeLens v1.9.3 extension helped showing the autocomplete result quicker. I wonder why it has started giving me issues only from last week!

Ravnurin commented 4 years ago

Here's something to try as a workaround if you have a beefy machine:

  • go to Settings in VSCode, and search for 'typescript memory', increase TypeScript › Tsserver: Max TS Server Memory to something like 8192.

I haven't had the opportunity to test this more extensively so if it works please let everyone know :)

I ended up trying this btw, and believe I saw a decent improvement. I remember checking memory usage after a lengthy coding session and if I recall correctly VSC was consuming ~6GB, lol.

collegeimprovements commented 4 years ago

In a small project of mine, I've started to have a watch process with noEmit specifically for *.tsx files. This gives significantly faster feedback (4-5 seconds) if something broke than IntelliSense, which takes forever to update.

How do you do that ?

SeriousJul commented 4 years ago

I'm actively working on this, but the changes aren't aimed at any particular TS milestone.

@amcasey , may I ask if you made any progress in your investigation ? Is there something we can do locally to mitigate ? I am thinking for example that if it is a single component that slows the entire project down, we could import it using require, loosing typings only on one component for the benefit of speed.

amcasey commented 4 years ago

@SeriousJul https://github.com/mui-org/material-ui/issues/19113 is the best place to track progress on this issue. The short answer is "yes" - we've fixed the regressions and are now looking at whether fundamental performance can be improved.

AlCalzone commented 4 years ago

@amcasey Just to give some additional feedback after working with 3.9 for a while. It is indeed much faster than 3.8 (as I wrote you via e-mail), but its still somewhat painful to work with. Even on a beefy machine (12-core Ryzen 9, 32 GB RAM), the following editor features are delayed by seconds whenever I edit a file that uses material-ui:

amcasey commented 4 years ago

@AlCalzone Thanks for the update! Unfortunately, when something is an order of magnitude too slow, even doubling the performance only gets you so far. We're still working on it.

vlopp commented 4 years ago

MUI grinds my laptop to a halt.

TSC: 3.7.5

VSC:

Version: 1.44.2
Commit: ff915844119ce9485abfe8aa9076ec76b5300ddd
Date: 2020-04-16T17:50:03.709Z
Electron: 7.1.11
Chrome: 78.0.3904.130
Node.js: 12.8.1
V8: 7.8.279.23-electron.0
OS: Linux x64 5.3.0-46-generic snap

For whatever reason, the same project is much faster in Webstorm, though unfortunately the 'much faster' still means 'painfully slow'.

WebStorm 2020.1
Build #WS-201.6668.106, built on April 6, 2020
amcasey commented 4 years ago

@vlopp, it should be dramatically faster (i.e. still painfully slow) in 3.9 beta (and newer).

zaguiini commented 4 years ago

WebStorm is really fast here using MUI + TS. It gives feedback after less than a second.

amcasey commented 4 years ago

@zaguiini I understood WebStorm was based on the same tsserver implementation as VS Code, so my guess would be that they have a heuristic bypassing tsserver in the scenario you're describing. Of course, I can't rule out their having some brilliant secret sauce.

Chnapy commented 4 years ago

I had the same issue, using MUI in a Typescript context, since I used the MUI components the type checking became very VERY slow (sometimes +15s !). In two projects, one medium size, another big size.

Some days ago I tried this solution https://material-ui.com/guides/minimizing-bundle-size/ which seemed to affect only the bundle size. After 3 days I can say this changed considerably type checking time (no more than 3s now). This changed my dev experience on this part of my project. I suggest people who have this issue to try this solution.

For the context, the project which I made the change follows the MUI doc directives, in a sense that imports are perf-safe (there is no import {} from '@material-ui/icons').

If this solution is validated by other people, it would be nice to edit the doc to add a Typescript performance part, something like that.

AlCalzone commented 4 years ago

@Chnapy I'm already doing that. I'm sure it helps the check times, but I have no direct comparison like you do.

Ravnurin commented 4 years ago

@Chnapy I am also already doing that and unfortunately to no avail.

anisg commented 4 years ago

Anyone experienced improvement recently?

I personally replaced import by good old nodejs require.

before (slow):

import Button from "@material-ui/core/Button"

after (no problem):

const Button = require("@material-ui/core/Button").default

in doing so, we loose intelisense for MUI components (no more typechecking when coding) but I guess that's ok, the website documentation is clear and the API straightforward.

effervescentia commented 4 years ago

in doing so, we loose intelisense for MUI components (no more typechecking when coding) but I guess that's ok, the website documentation is clear and the API straightforward.

@anisg Just to be clear why I don't think that recommendation is helpful is that the desired behaviour is to have the type-checking

Although it may be valid in your case to not have the types checked, the nature of this issue is that when types are being checked it is too slow to be used during development. Your solution does not solve this problem, instead sacrificing type-safety and intelligent linting for a faster build / validation time.

anisg commented 4 years ago

@effervescentia I agree it's just a small workaround, but I do prefer that than having a 300% CPU and a 3s autocompletion.

amcasey commented 4 years ago

I'm guessing Automatic Type Acquisition doesn't pull in the type definitions with that style of important, hence no IntelliSense and no delay.

For what it's worth, we haven't dropped this investigation - it's just hard. Basically, the type annotations for MUI require the compiler to do large, complicated computations. In order to speed things up without changing the semantics, we have to design new language features that allow the same constraints to be expressed in a way that can be checked more efficiently.

scscgit commented 4 years ago

Out of curiosity, as there were no alternative solutions mentioned yet, is there any chance for this to be an opportunity to split the process into multiple independent phases, or to provide some selective type-checking exclusion rules? If a similar situation ever occurs in the future, I'm sure people would prefer the option to see faster yet less accurate results while they wait for a longer background process, so that at least MUI-unrelated code is easy to work with. Is anything similar reasonable given the current implementation details?

amcasey commented 4 years ago

@scscgit That's possible when invoking the compiler through the API and I believe some tools already do, though I believe they only affect CI and not the editing experience. Allowing users to give up some type safety in exchange for improved performance is one of the options we're investigating.

wjohnsto commented 4 years ago

Correct me if I'm wrong, but it's possible that an issue here is the sheer amount of code that needs to be compiled when using something like MUI, which merges JSX, styles, and TS all into one. This combined with the additional declarations necessary to do tree shaking means there is a lot more code to compile than in an app where you might be using SCSS and HTML templates that have separate compilation processes outside of TSC.