Possible memory-leak or infinite recursion in type-checking algorithm.
See original GitHub issueBug Report
🔎 Search Terms
memory-leak type-checking tsc memory-limit not-enough-memory
🕗 Version & Regression Information
- This is a crash
- I have checked this on 4.5.4 and 4.5.5
⏯ Reproduce
I was developing a SQL query builder with TS main repo and I experienced some problems when I was using it. reproduce repo
git clone https://github.com/MRNafisiA/too-much-inferring
cd ./too-much-inferring
yarn install
./node_modules/jest/bin/jest.js
the test will be 1- type checked 2- transpiled 3- ran successfully. ( test will fail because it can’t connect to the database but It is OK. the point is, first phase(type checking) passed.)
go to ./src/index.ts comment lines 22 and 23 ( They are marked as “Correct” ) uncomment lines 25 and 26 ( They are marked as “Incorrect” ) and now try
./node_modules/jest/bin/jest.js
It will eat up your CPU and Memory and will be failed with memory-limit error after about 10 minutes. Obviously It is not a memory problem, because previous test executed with the same memory. you can increase memory with below command.
node --max-old-space-size=4096 ./node_modules/jest/bin/jest.js
But It will not help.
Error text ( in case you don’t want to wait 10 minutes)
<--- Last few GCs --->
[1458:0x7fc31ca00000] 331911 ms: Mark-sweep (reduce) 2043.6 (2082.4) -> 2042.7 (2082.4) MB, 3281.5 / 0.0 ms (average mu = 0.141, current mu = 0.002) allocation failure scavenge might not succeed
[1458:0x7fc31ca00000] 335398 ms: Mark-sweep (reduce) 2043.9 (2082.4) -> 2043.0 (2082.7) MB, 3478.4 / 0.0 ms (average mu = 0.074, current mu = 0.002) allocation failure scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0x10be15225 node::Abort() [/usr/local/bin/node]
2: 0x10be153a8 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
3: 0x10bf8c9c7 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
4: 0x10bf8c963 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
5: 0x10c12afe5 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
6: 0x10c12f00b v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/usr/local/bin/node]
7: 0x10c12b8ec v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
8: 0x10c128d9a v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
9: 0x10c1360f0 v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x10c136171 v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
11: 0x10c1030c7 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/usr/local/bin/node]
12: 0x10c4af0ae v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]
13: 0x10c8510b9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/bin/node]
// Correct
const removingIDs: TagGroup['id'][] = [];
const editingIDs: TagGroup['id'][] = [];
// Incorrect
const removingIDs = [];
const editingIDs = [];
As you can see, the difference is only on type definition. correct approach define types explicitly, but in incorrect approach, typescript must infer it. I think It is not hard to infer because array is modified only on one place.
🙁 Actual behavior and 🙂 Expected behavior
So, what is the problem? Actually, I don’t know. but I’m sure, I must get type error or successful build but out-of-memory after 10 minutes is not expected.
Thanks!
PS: After uncommenting Incorrect section, your IDE will hang(same reason as typescript type-checking hangs) and does not work properly. It will work with heavy lag and delay. to fix this, comment incorrect section and restart you IDE.
PS: if you think index.js has weird logic, It’s because I have extracted it from a real project. I tried to narrow it down for simplicity. So, It makes sense that It doesn’t make sense! but the code inside type-query must be in good shape. If you found a problem or bad design, I would be appreciated if you point it out.
EDIT:
You can use tsc
command and get same result. I only used jest
because It’s easier in IDE. the main problem is in type-checking not transpiling or running.
EDIT 2: I was reading TypeScript 4.5 release notes and I saw this tail-recursion. I have infinite recursion in Expression type. but It seemed that type script can not detected in this particular example.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:5
- Comments:7 (4 by maintainers)
Ah, thanks, I misread which state the repo was initially in.
@RyanCavanaugh Did you try after making the change mentioned in the OP? I was able to repro after doing that:
npx tsc --noEmit --extendedDiagnostics
is now still going over 10 minutes later.Edit: Still going 20 minutes later. No crash yet, but I do have 32GB of RAM so maybe it would just take longer. Node’s memory usage was nearing 4GB and still climbing a minute or so before I killed it: