-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SR-7632] Initializing an Int Array with 2000 elements takes more than 4 seconds #50173
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
Comments
cc @xedin |
Comment by Andreas Wendleder (JIRA) The offending functions found with perf:
|
Comment by Andreas Wendleder (JIRA) perf top from a release build without assertions (which also gets rid of SILVerifier):
|
I think @rudkx has a couple of ideas how to use Type::join to optimize this. andreasw (JIRA User) meanwhile you can workaround the problem by giving array explicit contextual type. |
Comment by Andreas Wendleder (JIRA) I tried let x: Array<Int> = [ Int(1), Int(2), ..., Int(2000) ] which is not better (~30s). Or do you think of something else? |
Comment by Andreas Wendleder (JIRA) After reading https://forums.swift.org/t/proposal-t-literal-should-construct-t-using-the-appropriate-literal-protocol-if-possible/2861 I tried: let x: Array<Int> = [1 as Int, 2 as Int, ..., 2000 as Int] which takes 0,3s which is much better. With 5.000 elements it is 1,2s, for 10.000 4,4s, for my matrix size of 50.000 it is 1m58s which is still not acceptable. |
I believe we have quadratic or worse behavior in the constraint graph edge contraction pass, which is showing up in these cases with large numbers of elements in a statically initialized array. |
There is definitely extra work happening in edge contraction, but that doesn't account for all the slowness here. |
andreasw (JIRA User) problem with both |
Comment by Andreas Wendleder (JIRA) Timings for
Still unusable for my 50.000 element matrix. 🙁 This is a self-compiled swift with The offending functions recorded with perf are:
|
Very interesting, @rudkx has an idea how to make |
andreasw (JIRA User) I have PR for this if you want to give it a try - #16560 |
Comment by Andreas Wendleder (JIRA) Much better! I would say it's usable now, but still far from clang.
Numbers generated with: echo "let x: [Int] = [" > linear.swift; seq -s, 1000 >> linear.swift; echo "]" >> linear.swift ; time swiftc linear.swift
echo -e "#include <vector>nstd::vector<int> x{" > linear.cc; seq -s, 1000 >> linear.cc; echo "};" >> linear.cc ; time clang -c linear.cc Thanks very much. |
Comment by Andreas Wendleder (JIRA) And for the sake of completeness the offending functions now:
|
Comment by Andreas Wendleder (JIRA) This can be brought down to
when each element is written to its own line with echo "let x: [Int] = [" > linear.swift; for i in $(seq 50000); do echo -e $i,; done >> linear.swift; echo "]" >> linear.swift ; time swiftc linear.swift which means that the Source Manager is doing some redundant work while trying to find a newline for each element. Maybe the Line Number Cache in |
Comment by Andreas Wendleder (JIRA) Offending functions after that:
|
Interesting, I think we need to CC performance people @eeckstein [email protected] (JIRA User) @bob-wilson |
Comment by Andreas Wendleder (JIRA) And for an array of Doubles: echo "let x: [Double] = [" > linear.swift; for i in $(LANG=C seq -f%f 50000); do echo -e $i,; done >> linear.swift; echo "]" >> linear.swift ; time swiftc linear.swift
|
Comment by Andreas Wendleder (JIRA) FWIW, I can throw arrays like that at clang++ and g++ as int, float and double, and even initialize a double array with 50.000 integer literals, and compile time always stays around 0.3s. That is what I would be expecting. |
Comment by Andreas Wendleder (JIRA) And the original test without an explicit type is slower, too: echo "let x = [" > linear.swift; seq -s, 10000 >> linear.swift; echo "]" >> linear.swift ; time swiftc linear.swift
|
I tried with an assert build of master and got ~1sec build time (on a good machine). |
Pavel's recent type checker change fixed the type checker issue. |
Comment by Andreas Wendleder (JIRA) Yes, Pavel resolved my first concern. @eeckstein, You may try an array of 50.000 Doubles (my matrix size). Time on my moderately powered notebook is 40 seconds. |
We have in fact a quadratic complexity here. It's in the SIL verifier. The verifier does not run in no-assert compiler builds, but I think the linux toolchains contain an assert build. Without the verifier I got a 10000 element array compiled in 6s (vs 40s). The 6s are spent in the type checker. With an explicit type annotation on the array the time goes down to 0.5s. There is also some overhead in the optimizer. When compiling with optimizations we spend 10s in the optimizer. This is a separate issue. Anyway, thanks for reporting! |
My changes (#16560 for type-checker got merged into master, should be available in the next nightly snapshot, but since you've ready tried them out I think should could just close this JIRA and open separate one for optimizer performance... |
Comment by Andreas Wendleder (JIRA) @xedin, an acknowledgement for spotting the right function (contractEdges) in the commit message would have been nice. I opened another issue for the problem with the Source Manager. After that I will try an optimised build. |
Comment by Andreas Wendleder (JIRA) The problem in |
Sorry about that andreasw (JIRA User), and thanks for helping out with diagnosis! |
Environment
Ubuntu 17.10, Swift 4.1, Dell Latitude
Additional Detail from JIRA
md5: c140d89b8695a1d83b04eca03543c3fc
Issue Description:
Compilation of
takes >4 seconds on my laptop.
The same in C++ with clang takes less than 0.2 seconds.
It gets worse with 5.000 or 20.000 elements, numbers that are not unusual when working with large predefined matrices.
I generated the elements with bash:
The text was updated successfully, but these errors were encountered: