Closed DanielRosenwasser closed 3 months ago
@amcasey do you have that version of the compiler that can print out how many types a given statement is generating?
@DanielRosenwasser I'm planning to create a PR for an productized version of this, but the rough version is here: https://github.com/microsoft/TypeScript/pull/37417
It dumps a csv to stdout.
Thank you guys for posting my issue here. I'm sorry I've originally posted it in the roadmap.
The issue I have might be related to how my codebase is organized or how big it is (it has 890 ts/tsx files).
Let me know if I can provide any additional input / prepare some logs (if so what exactly would be useful for you and how can I collect it). I'd prefer to not give you access to the full repo as it's a private project.
I'm also opened to have some session with you showing anything you'd want to see about it.
Some insights:
styled-components
which is known to slow down TSexport * from './file.ts
It works like I have ui/buttons
folder and inside this I've got bunch of other folders eg PrimaryButton.tsx
, CircleButton.tsx
etc. Often I've got 10-20 files like this
Then in ui/buttons/index.ts
I re-export all of them like export * from './PrimaryButton'
so I can import in later anywhere like import { PrimaryButton } from '~app/ui/buttons'
I use quite a lot of VS Code plugins, but I've tried to work without them and it still happens to become very slow / unreliable
I'm using paths
to create an alias for my root src
called ~app
and I use it in most of the files in the app.
I've got a lot of generic functions
I often use pattern when I wrap something inside generic function eg
export function createAsyncStorage<T>(storageKey: string) {
// here I've got get/set methods that will cast JSON in storage to T type
return {
get() {
return asyncStorage.get() as T;
}
}
}
// then in the app in many places I do something like
export const someStorage = createAsyncStorage<{foo: string, bar: number}>('baz');
// than in other place in the app I import it and use typed version
someStorage.get().bar // typed as number properly
@pie6k Thanks for the details! We have a few avenues we can pursue for figuring out what's taking so long.
1) It's pretty helpful to have the output with --extendedDiagnostics
2) You can generate a CPU profile with --generateCpuProfile
- it shouldn't contain any of your code or paths, but it's a json file, so feel free to double check
3) The PR I linked above has a private build that dumps a CSV to stdout with the cost of each statement - you can sort it in your spreadsheet program of choice to figure out if there's a section that's unexpectedly expensive (and, ideally, extract that bit into a smaller repro program for us)
If you normally use an incremental build, please be sure to clean before gathering any of the above.
I've managed to get some error info
I was trying to get auto-import suggestions for LayoutAnimation
which is part of react-native.d.ts
, but it was not working around 5 times when I pressed 'CMD + Space', then I've mineralized VS Code and tried again and it worked, I've opened logs and I've got this
Info 2745 [14:10:13.943] getCompletionsAtPosition: isCompletionListBlocker: 0
Info 2746 [14:10:13.949] getSymbolsFromOtherSourceFileExports: Using cached list
Info 2747 [14:10:13.955] getCompletionData: Semantic work: 12
Err 2768 [14:10:16.395] Exception on executing command {"seq":2076,"type":"request","command":"completionEntryDetails","arguments":{"file":"<MY_PROJECT_ROOT>/src/ui/interactions/EditableList/index.tsx","line":60,"offset":18,"entryNames":[{"name":"LayoutAnimation","source":"<MY_PROJECT_ROOT>/node_modules/@types/react-native/index"}]}}:
Debug Failure. False expression: Some exportInfo should match the specified moduleSymbol
Error: Debug Failure. False expression: Some exportInfo should match the specified moduleSymbol
at getImportFixForSymbol (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:128841:22)
at Object.getImportCompletionAction (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:128836:23)
at getCompletionEntryCodeActionsAndSourceDisplay (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:111727:33)
at Object.getCompletionEntryDetails (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:111691:30)
at Proxy.getCompletionEntryDetails (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:137830:35)
at <MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:147930:57
at Object.mapDefined (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:562:30)
at IOSession.Session.getCompletionEntryDetails (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:147928:33)
at Session.handlers.ts.createMapFromTemplate._a.<computed> (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:146850:61)
at <MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:148476:88
at IOSession.Session.executeWithRequestId (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:148467:28)
at IOSession.Session.executeCommand (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:148476:33)
at IOSession.Session.onMessage (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:148500:35)
at Interface.<anonymous> (<MY_PROJECT_ROOT>/node_modules/typescript/lib/tsserver.js:149816:27)
at Interface.emit (events.js:203:13)
at Interface._onLine (readline.js:316:10)
at Interface._normalWrite (readline.js:461:12)
at Socket.ondata (readline.js:172:10)
at Socket.emit (events.js:203:13)
at addChunk (_stream_readable.js:295:12)
at readableAddChunk (_stream_readable.js:276:11)
at Socket.Readable.push (_stream_readable.js:210:10)
at Pipe.onStreamRead (internal/stream_base_commons.js:166:17)
About the flags you've mentioned @amcasey - I'm not compiling the code myself as React-Native uses a metro compiler. So I don't have direct control about starting ts-server probably.
Can I include those flags to the VS Code typescript engine somehow? (I've tried to enable it in my vs code settings but it seems there is no such option).
So in general - I never compile TS 'myself'. My issues are solely related to editing experience in my ide typescript engine (VS Code). I'm not sure where can I enable those flags eg. extendedDiagnostics
in such case
Running TSC on my files (with noEmit) gives
Files: 1353
Lines: 292940
Nodes: 876492
Identifiers: 294654
Symbols: 348688
Types: 90647
Instantiations: 845537
Memory used: 391677K
Assignability cache size: 30362
Identity cache size: 2670
Subtype cache size: 9264
Strict subtype cache size: 985
I/O Read time: 0.12s
Parse time: 1.25s
ResolveTypeReference time: 0.02s
ResolveModule time: 0.88s
Program time: 2.42s
Bind time: 0.78s
Check time: 4.99s
Total time: 8.19s
I'm attaching CPU profile for tsc
command
I've also run CSV tool, it's hard for me to have some solid insights from it - I've got 10280 rows, but only around ~~200 of first ones have deltas bigger than 100
I'm not sure if there is some way that would help me analyze those stats to eg. divide operations by category or detect some operation that is repeating all the time.
Number one element is this:
const Animator = styled(Animated.View)`
z-index: 2;
flex-grow: 1;
`;
where seems like Animated.View
is from react-native and is dynamically computing all the props (converting all regular styles like height: number
to animated values like height: Animated.Value
(not sure but I guess it happens looking briefly on definitions). Not sure how often it happens in my codebase in total, but for sure those props are rarely used by me (as views have probably 200+ properties related to styles only, but I'm using only 2-3 of them - not sure if it's possible to make it somehow computed in a lazy way eg. only get the list of properties, but compile type of interface properties only if it's actually used ie. to validate some value or to provide a type of selected autocomplete property)
eg. (note I'm totally guessing here)
If I write
function foo() {
return <Animated.View style={{
height: new Animated.Value(100),
}} />
}
I actually don't need to have all types of possible style properties compiled by TS, I only need to validate that height
value is matching interface and that I'm not missing any required property (part of the interface without ?
after property name)
Same with autosuggestions - if I want to add another style property - the first thing that is interesting for me is the name of this property - eg. opacity. If I type 'opa' - I see 'opacity' in the dropdown and this is the moment when the type of this property starts to be meaningful for me. I also don't really care about types of other (even auto-suggested) interface properties until I highlight them.
Again, this is just guessing - I have no idea how it actually works under the hood.
Thanks for the call stack - that's https://github.com/microsoft/TypeScript/issues/32853 (which is woefully out of date - we're getting a lot more hits now). I don't suppose you can share a code fragment that reproduces the issue? We've had trouble figuring out how it could happen.
Regarding switches, I'm sorry for being unclear - all of my suggestions were for command line builds because that was top-of-mind from my recent investigations. In any case, command line build stats tend to tell us useful things about the project that apply to the editor as well.
I'm still looking at the perf data you've supplied - I'll reply to that separately.
FWIW, I suspect your auto-complete woes are separate from any perf problems you're seeing (except insofar as one library may prove to trigger both). What other slowness are you seeing? Completions? Go-to-definition? Spinning "Initializing Project" in the status bar?
The first row in the CSV is basically guaranteed to be large, because it'll cause a bunch of library types to be created. interactions/drag/index.tsx
wasn't first before you sorted, was it?
Other than that, we're looking for a few rows with big deltas and a lot of rows with little deltas. As you've suggested, probably only the top five are interesting. In this case, it sounds like they'll all point at TSX elements, probably ones using StyledComponents and/or React Native. I think you might already be using TypeScript@next, but you may want to try refreshing to pick up this change: https://github.com/microsoft/TypeScript/pull/37749.
There's already laziness around instantiating mapped types (frequently used in StyledComponents), but I can look into being even lazier. My guess is that structural type comparisons will almost immediately require the full type to be instantiated.
Still looking at the profile...
I don't see anything in the CPU profile that jumps out as different from a normal StyledComponents slowdown - if anything, less time is spent in JSX overload resolution than I would expect.
Okay, I confirmed with someone more knowledgeable that we're already computing property types lazily, so that's probably not the issue.
Doesn't seem like we managed to get anywhere else with this. We'll need an up-to-date repro to investigate further - please open a separate issue.
Hello TS Team!
I appreciate your efforts to improve typescript performance! I'm very happy using TS, but as my project (react native) grew performance started to fall so badly, that it's the biggest factor impacting my productivity.
I have to reset TS server ~every 30 minutes (I'm using VS Code), quite frequently more often than that. Autocomplete with auto-import often works in a weird way - it properly suggests a variable name, but when I use it - it's not importing needed module. Sometimes I have to CMD+Space to see import suggestions, but sometimes it does not work and I have to manually write imports. Often autosuggestions start to work so slowly (3-10s) that it becomes unusable.
I'd like to help you by providing some feedback, but I actually don't know how to collect needed data. I've tried to enable verbose logs, but I'm getting a huge amount of logs (often more than 50mb) which includes so much noise, that I actually have no idea what is going on.
It would be very useful to have some sort of guide related to actually detecting and narrowing down issues with the ts server. It would be awesome to have some 'smart' diagnostics tool that would be able to tell something like 'this module types took 80% of time needed for suggestions collection caused by your last CMD+space'
I'm open to having some sessions with you trying to reproduce the issue. I don't have any specific scenario. Sometimes it works just fine for 2 hours after restarting TS server and sometimes I have to restart it every 10 minutes so I'm worried I'll waste your time if I'll not be able to reproduce it. If you're interested, however - I'd be more than happy to help as much as I can.
Screen Recording 2020-04-02 at 10.44.43 PM.mov.zip
I'm sending screen recording with issue - when I'm typing - it suggest proper variable name I can import, but when I use it - it's not actually imported. I have to CMD+Space at the end of it again to make VS Code suggest me to import given variable
Originally posted by @pie6k in https://github.com/microsoft/TypeScript/issues/33118#issuecomment-608081358