-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debugging long check times with TypeScript? #24435
Comments
After much effort, I finally shifted around enough code that the compiler terminated. I would still like to know if there's anything I can do to debug these long compile times, though. |
60s+ compile times generally indicate a bug on our side unless you have truly huge amounts of code. Is the linked repo sufficient to reproduce the issue, and if so what are the steps to do so? |
Yeah, the linked repo is enough to reproduce the issue. I guess just,
I just tried building again and got
I'm not sure if the project can be considered super-huge; it's certainly smaller than the TypeScript project, itself. [EDIT] That's weird. The check time above is I just checked a bunch of previous commits, too. And it seems like all the check times are now 20-30s... Now I look foolish =/ I was getting 60s check times for at least a week, and it all goes away 3 days after I submit a question. I didn't even restart my computer, or anything (for the past week). My original problem with It looks like it still causes
|
It seems like using the generated Initially, a personal project of mine had
I assumed it must be the sheer number of files. So...
After removing about 1800 files, check times only improved by about I thought I might need to reboot my computer,
Still pretty long, I decided to modify the
Check times improved a lot to I added just one file to the check, which was using
The one usage of const reading = await this.db.from(t.readingComponent)
.whereIsEqual(c => c.readingId, readingId)
.orderBy(c => [
[c.sortOrder, true]
])
.leftJoinUsing(t.furiganaReadingComponent, c => [c.readingComponentId])
.leftJoinUsing(t.ideogramReadingComponent, c => [c.readingComponent.readingComponentId])
.leftJoinUsing(t.ideogram, c => [c.ideogramReadingComponent.ideogramId])
.selectAll()
.fetchAll()
.then((components) => {
//Using Promise.all() because I planned to add another `component` that would require a database call to compute the furigana and logogram
return Promise.all(
components.map((component) => {
if (component.furiganaReadingComponent != undefined) {
return {
furigana : component.furiganaReadingComponent.furigana,
};
}
if (
component.ideogramReadingComponent != undefined &&
component.ideogram != undefined
) {
return {
furigana : component.ideogramReadingComponent.furigana,
logogram : component.ideogram.logogram,
};
}
throw new Error(`Unknown reading component ${component.readingComponent.readingComponentId}`);
})
);
}); I've tried commenting out the
|
I made the usage, const reading = await this.db.from(t.readingComponent)
.whereIsEqual(c => c.readingId, readingId)
.orderBy(c => [
[c.sortOrder, true]
])
.selectAll()
.fetchAll() And got,
With the following, const reading = await this.db.from(t.readingComponent)
.whereIsEqual(c => c.readingId, readingId)
.orderBy(c => [
[c.sortOrder, true]
])
.leftJoinUsing(t.furiganaReadingComponent, c => [c.readingComponentId])
.leftJoinUsing(t.ideogramReadingComponent, c => [c.readingComponent.readingComponentId])
//.leftJoinUsing(t.ideogram, c => [c.ideogramReadingComponent.ideogramId])
.selectAll()
.fetchAll()
With the following, const reading = await this.db.from(t.readingComponent)
.whereIsEqual(c => c.readingId, readingId)
.orderBy(c => [
[c.sortOrder, true]
])
.leftJoinUsing(t.furiganaReadingComponent, c => [c.readingComponentId])
.leftJoinUsing(t.ideogramReadingComponent, c => [c.readingComponent.readingComponentId])
.leftJoinUsing(t.ideogram, c => [c.ideogramReadingComponent.ideogramId])
.selectAll()
.fetchAll()
A spike of about 130s with one line of code. It seems like the code for I tried to simplify it, leftJoinUsing<ToTableT extends AnyAliasedTable, FromDelegateT extends JoinFromDelegate<DataT["joins"]>>(this: SelectBuilder<{
hasSelect: any;
hasFrom: true;
hasUnion: any;
joins: any;
selects: any;
aggregateDelegate: any;
hasParentJoins: any;
parentJoins: any;
}>, toTable: ToTableT, fromDelegate: FromDelegateT): (
//Error extends JoinCollectionUtil.LeftJoinUsing<SelectBuilder<DataT>, ToTableT, FromDelegateT> ?
//JoinCollectionUtil.LeftJoinUsing<SelectBuilder<DataT>, ToTableT, FromDelegateT> :
SelectBuilder<{
readonly [key in keyof this["data"]] : (
key extends "joins" ?
TupleWPush<
AnyJoin,
this["data"]["joins"],
Join<ToTableT, ToTableT["columns"], true>
> :
this["data"][key]
)
}>
); This gave me a
|
At this point, the only conclusion I have is that the type aliases in my |
I refactored export type TupleWPush<WidenT, TupleT extends Tuple<WidenT>, NextT extends WidenT> = (
{
[index in TupleKeys<TupleT>] : (
TupleT[index] extends WidenT ?
TupleT[index] :
never
)
} &
{
[index in TupleNextKey<TupleT>] : (
NextT extends WidenT ?
NextT :
never
)
} &
{
"0" : (
TupleT[0] extends WidenT ?
TupleT[0] :
never
),
} &
{
length : TupleNextLength<TupleT>
} &
(
WidenT[]
)
); And it ran in
It was originally, export type TupleWPush<WidenT, TupleT extends Tuple<WidenT>, NextT extends WidenT> = (
TupleWiden<TuplePush<TupleT, NextT>, WidenT>
); Which I suppose is really inefficient. |
@RyanCavanaugh Sorry for all the spam. It's just been a really mentally draining issue for me to debug. I had to use the I don't really know what to do with this issue anymore. On one hand, the problem is resolved for me, for now. On the other hand, I'm worried I'll encounter something like this again in future. I've always found existing SQL query building libraries very lacking in the structural, and type safety departments. Always needing string literals in queries, or trusting that a type is what it says it is, and trusting that the columns you say exist in the query actually do come out, etc. TypeScript is my first exposure to a type system that has enabled me to experiment with a query building library that doesn't expose any of those hacks to the user. It's basically my favourite language at the moment, and I wouldn't even touch JS with a ten-foot pole. I do have a few things that I would like to see in TypeScript after going through this ordeal, though (I am unsure if proposals have been written for them). None of it's a serious proposal, just throwing some thoughts out there.
type Map<ObjectT, TypeFunctionT> = (
{
[key in keyof ObjectT] : TypeFunctionT<ObjectT[key]>
}
);
type SomeTypeFunction<T> = (
T extends string ? T : ["T is not a string", T]
);
type X = Map<
{
field0 : "a string",
field1 : ["not", "a", "string"]
},
SomeTypeFunction //As far as I know, there's no way to do this but to copy-paste code around
> I have generic types that map one type to another quite often in my personal projects. I see myself copy-pasting the same mapping boilerplate code every now and then.
If I had seen that But I don't know how feasible such a thing is. Should this issue be closed? Or should I leave it open? |
I'm quite interested in this issue, it seems that @AnyhowStep and I have run into a class of typescript bugs that make typescript performance crippling slow. But there are not good methods to identify what is causing the method and how to fix it today. |
FYI I added the debug information that helped me solve my case of this in this post: |
It's quite possible that #37785 would allow people to start introspecting at what point the code is getting to be expensive |
I love you all <3 |
Great point, I'm going to keep this open till |
I presume this is the documentation in question. tsc --generateTrace logsDir
# in other terminal
tail -f logsDir/trace.json Outputs:
Great thanks to @amcasey! |
It is, thank you |
TypeScript Version: 2.9.0-dev.20180516
I have a toy project I've been working on and, in general, it takes about 50-60s to type check, and, sometimes, I get out of memory exceptions.
I'm unsure if such wait times are normal or if it's just me.
I'm finally writing this question because I added one method to a class and it caused
tsc
to not terminate. I've waited over twenty minutes and it's still not ending.If I comment out the method I just added, I can get
tsc
to terminate without errors.The code in question is here
(Ignore that the folder is called
declaration-v2
, I never got around to renaming it)Is there a way to get
tsc
to output what phase of the check it's at and what files it's reading as it checks, etc.?Something like,
--listFiles
isn't particularly helpful for this case because it outputs that at the end, andtsc
won't even terminate at the moment.Or are there other guidelines I can use to debug long check times?
I understand the type system is very complex but I feel my productivity has been taking a huge hit when I can barely get IntelliSense and type checking to work with VS code, and Atom with
atom-typescript
just crashes, (I assume it's related to the long check times) and have to resort to using the terminal every once in a while to sanity check my code.I understand that this issues page is not for questions like these but I've found the answers on StackOverflow unsatisfactory, and sitting here waiting for
tsc
to terminate is kind of frustrating.I'm unsure if I can even reduce this to a minimal example because the project is huge. But at least I've found the method to comment/uncomment to reproduce the issue.
[EDIT]
This is also the first time I've encountered this problem. I'd actually be relieved if I could get an out of memory exception right now. Memory usage is actually surprisingly low. But it's just not terminating...
Maybe an infinite loop?
The text was updated successfully, but these errors were encountered: