-
-
Notifications
You must be signed in to change notification settings - Fork 640
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
Improve time complexity of traverseIndirections
#12885
Improve time complexity of traverseIndirections
#12885
Conversation
Thanks for your pull request and interest in making D better, @dkorpel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#12885" |
This error is missing now in fail_compilation/testInference.d:
So I guess not. |
DsymbolTable only looks at identifiers, and identifiers are interned strings. |
234e22b
to
5008d47
Compare
I learned that |
traverseIndirections
This is green, is it good to go? |
One thing left to do is check whether my |
It would be interesting to see what is the memory footprint of this. I suspect that it should be negligible. |
5008d47
to
926b6b5
Compare
I was profiling the build time of DMD and noticed the host compiler spent a very long time on
StructDeclaration.finalizeSize
.It turns out that 300 ms of semantic analysis time is spent on the following line:
When using my self-built dmd instead of an official release as host compiler, it's even 800 ms.
So I walked down the call stack of the function that analysed that line, looking for the culprit:
And there you had it:
traverseIndirections(inout(UnionDeclaration), inout(Dsymbol))
took all the time. What's happening is that all fields ofDsymbol
are recursively walked looking forUnionDeclaration
, which can take a while, sinceDsymbol
is huge andUnionDeclaration
is pretty deep in the hierarchy:But the worst thing is that there is no memoization. There is a simple cycle checker that walks back a linked list, but if
Dsymbol
can reach a field of e.g. typeSymbol*
in 50 different ways, it will walk down all fields ofSymbol
50 times, and do that recursively in the same inefficient way.This PR tries to solve it by inserting fields it visits into a
DsymbolTable
, and quitting when it's already there. This not only replaces the old cycle checker, but also prunes redundant branches. The amount of calls totraverse
went down from 1145127 to 1041. The frontend build time of dmd (no codegen) went down from 3.4 to 2.6 seconds, measured with this command:time dmd -version=MARS -Jdmd/res -J.. -i -o- dmd/mars.d
I have yet to test it on other codebases, I'm open for suggestions of codebases that you suspect have super complex aggregate definitions like
Dsymbol
.I hope the algorithm is still correct, I assumed
type.toDsymbol()
andDsymbolTable
handle type modifiers (inout
in this case) like I expect, but I have yet to check.