Repository navigation
Performance regression from #48044 #52345
Description
Activity
DanielRosenwasser commented
on Jan 21, 2023 MemberMore actionsWould you be able to generate a trace and use our analyze-trace tool?
https://github.com/microsoft/typescript-analyze-trace
It should highlight specific hot spots that might occur as of TS 4.7. The usage instructions are a little better now. Let me know if you need any more info using it.
- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Jan 24, 2023 Will Stamper (@epmatsw) In lieu of a small repro, is your code public such that I can test it out?
The above tracing mechanism should get you some info about which types are problematic, but to work on this I do need something, so even the full thing would be helpful.
Not public, unfortunately. Sorry about the delay on the trace, I’ll try to get something going tomorrow.
Dang, thought I had a reproduction but apparently not. Probably not gonna get something until Monday now :(
Okay, so I'm not sure this is minimal, but I think it's on the right track:
type R = `${number}a` & { _thing: true; }; type _S = "1" | "2" | "3" | "4" | "5"; type S = `${_S}${_S}`; // Produces "Expression produces a union type that is too complex to represent" // type S = `${_S}${_S}${_S}`; type T = R | S; type X = `${T} ${T}`; export type Props = Partial<{ x: X; }>; const a1: Props = {}; const a2: Props = {}; const b = { ...a1, ...a2 }; export { b };
In 4.6.4, that has a Strict subtype cache size of 0. In 4.7.4, that has a Strict subtype cache size of 34476.
Hmmm. I guess because X boils down to
stringin 4.6.4. So I'm not sure how useful that even actually is other than "actually checking this gigantic type rather than not checking it is expensive" :/That might be enough, actually. By modifiying it a bit to try and make it worse (but not enough to make it go to
string), I can get the test to take a good 5-6 seconds on my machine, wheras in v4.6, it takes under a second.type R = `${number}a` & { _thing: true; }; type _S = "1" | "2" | "3" | "4" | "5" | "6"; type S = `${_S}${_S}${_S}`; type T = R | S; type X = `${T} ${T}`; export type Props = Partial<{ x: X; }>; const a1: Props = {}; const a2: Props = {}; const b = { ...a1, ...a2 }; export { b };
Reacted by Toni VillenaReacted by Toni Villena, Will Stamper and Johan SundströmAfter staring at this for a while, I'm at a loss for a way to speed this up; we're now actually traversing the intersections whereas before, we weren't. This example in particular turns into a combinatorial explosion after #48044, which I didn't really see coming at the time.
I'm not sure what the path forward is at the moment, besides reverting that PR (or doing nothing), but I'll keep trying.
Reacted by Toni VillenaWill Stamper (@epmatsw) Would you mind testing the package on my PR for this issue here? #52836 (comment)
I believe it fixes the performance problem (in that it avoids massive intersections), but, it does make these sorts of constructs stricter (more correct in some situations) and the above sample in particular will still give an error that complains about it being too big.
EDIT: updated the link to the latest version
- addedFix AvailableA PR has been opened for this issueA PR has been opened for this issue
on Feb 18, 2023 Unfortunately not a huge improvement:
TS 4.6.4
Strict subtype cache size: 24040 Total time: 34.40sTS Version 5.0.0-insiders.20230218 (https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/146938/artifacts?artifactName=tgz&fileId=E6600AFB90EEF24611686B292C01E0D427A0C8AA2B90E3E4B7E85880B3CF614102&fileName=/typescript-5.0.0-insiders.20230218.tgz):
Strict subtype cache size: 122673 Total time: 65.03sJust to confirm, it's ~13s faster than a previous 5.0 build, correct?
29 remaining items
epmatsw commented
on Sep 30, 2023 on Sep 30, 2023 · Hidden as off-topicAuthorshow commentMore actionsepmatsw commented
on Sep 30, 2023 on Sep 30, 2023 · Hidden as off-topicAuthorshow commentMore actionsepmatsw commented
on Sep 30, 2023 on Sep 30, 2023 · Hidden as off-topicAuthorshow commentMore actionsSo barring the stuff in #55948, is there anything left here that isn't fast? I've gone through the code bits in this thread and they have all improved, and I can't really recall what's left here. It'd be nice of course to actually be able to test the real world example... I am of course happy to test it and if privacy is a concern I'm pretty sure we do NDAs.
- addedDomain: PerformanceReports of unusually slow behaviorReports of unusually slow behaviorand removedFix AvailableA PR has been opened for this issueA PR has been opened for this issue
on Oct 12, 2023 I think it's safe to call this one fixed! The remaining regression since 4.6 is fully accounted for by the issue we're tracking in the other thread.
Bug Report
It seems like a fairly significant performance regression was introduced in this #48044, which was shipped in TS 4.7. In TS 4.6, it takes ~30 seconds to run
yarn tscin our repo, and the reported strict subtype cache size is 24_011. In TS 4.7, it takes 75+ seconds to runyarn tsc(~2.5x longer than previous), and the reported strict subtype cache size is 122_778 (~5x larger than previous).I verified that it was that specific PR that regressed the performance by taking a locally-installed 4.6.4 and applying the changes from that PR directly.
Another symptom is that several types (mostly spreads of objects into others) are now reporting as "Expression produces a union type that is too complex to represent."
🔎 Search Terms
Expression produces a union type that is too complex to represent,strict subtype cache size🕗 Version & Regression Information
💻 Code
I haven't been able to narrow down a minimal reproduction of this issue, but if someone points me in the right direction I'm happy to work on it.
🙁 Actual behavior
Running
yarn tsc --noEmit --extendedDiagnosticstakes ~75 seconds in our repo, with a Strict subtype cache size of 122778.🙂 Expected behavior
Running
yarn tsc --noEmit --extendedDiagnosticstakes ~30 seconds in our repo, with a Strict subtype cache size of 24011.