-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Reduce the Stack Size of ConstraintSystem #24659
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
Conversation
I'd be really interested to know what expressions did you catch this on? It has to be big literal arrays or something similar... I think this is more of a workaround for actual problem which is related to the way we handle independent sub-components in the solver at the moment. We shouldn't need to move data in/out to/from original |
@xedin This one was from cursor_info_container.swift, running However, while it might be possible that the solver is allocating too much at run time, and I'd be happy (if a bit slow) to look at having the solver use ArrayRefs, I think a lot of the issue is just that a there are a lot of locals statically. For example, here's the stack trace of the first overflow I ran into (not with the solver). It lists the size of just the locals used (the amount subtracted from rsp) in each frame. It uses about 2/3 of its stack space with just locals, not even counting any runtime stack allocations/pushing. Note that |
One future improvement would be to investigate the places where we spin up new ConstraintSystems and see if they can be rewritten in a simpler way. I've seen various bits of code use a ConstraintSystem to check subtype and conformance relationships; this is overkill and should be avoided. |
It is overkill, but it's probably not causing these stack overflows, since they're always simple systems. |
@jrose-apple I suspect the stack overflow is not from the size of the constraints themselves but the large number of vectors and DenseMaps that are directly stored inside the instance. |
I…guess we stopped trying to measure memory usage in the compiler perf tests. (It was never great anyway.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM. I wouldn't expect performance to suffer here, because there's a lot of allocations already going on in the solver, and these particular bits of state are likely to either empty to blow through the small buffers anyway.
lib/Sema/TypeChecker.h
Outdated
@@ -603,7 +603,7 @@ class TypeChecker final : public LazyResolver { | |||
/// } | |||
/// } | |||
|
|||
llvm::SmallDenseMap<AnyFunctionRef, SmallVector<AnyFunctionRef, 4>, 4> | |||
llvm::DenseMap<AnyFunctionRef, SmallVector<AnyFunctionRef, 4>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This particular change probably doesn't do much, because there's only really one TypeChecker
instance that lives forever.
lib/Sema/TypeChecker.h
Outdated
@@ -549,7 +549,7 @@ class TypeChecker final : public LazyResolver { | |||
std::vector<AbstractFunctionDecl *> definedFunctions; | |||
|
|||
/// Declarations that need their conformances checked. | |||
llvm::SmallVector<Decl *, 8> ConformanceContexts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This particular change probably doesn't do much, because there's only really one TypeChecker instance that lives forever.
The ConstraintSystem class is on the order of 1000s of bytes in size on the stacka nd is causing issues with dispatch's 64k stack limit. This changes most Small data types which store data on the stack to non small heap based data types.
ac19610
to
e51b72b
Compare
Alright, removed the TypeChecker changes. @swift-ci please test and merge |
I've been looking at the sourcekit tests on Windows and have been running into stack overflows. The issue is not too much recursion, but rather one of huge stack frames in normal operation. For example, the ConstraintSystem class is on the order of 1000s of bytes in size on the stack. This becomes a problem with sourcekit which runs dispatch threads that have a hard coded 64k stack limit.
I don't see a single spot that's causing all the problems, I've seen it stack overflow so far with two entirely different stack traces. (Though one of them was probably caused because swift::Lexer::kindOfIdentifier uses 9992 bytes of stack on Windows and 12736 on Darwin.) I think most of this will be finding large classes and functions and either making them smaller, or instantiating them on the heap instead of the stack.
This commit changes ConstraintSystem from using Small data types which store data on the stack to non small heap based data types.
As numbers go, this reduces the stack frame size of
ResolvedMemberResult swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name)
from 4824 bytes to 2584 bytes (measured on a Windows Release build). The numbers are taken from looking at thesub rsp
instruction in the function's dissassembly. e.g:I've only noticed the stack overflows on Windows so far. Windows in general does seem to allocate slightly more stack space than Darwin and I'm not sure why that is yet. For example, for one stack overflow I traced through, I counted up 48440 of used stack space on Windows and 41288 on Darwin at the same (non crashed) point.