Repository navigation
Typechecking memory use #31849
Copy link
Copy link
Closed
Labels
A-type-systemArea: Type systemArea: Type system
Description
Typechecking the rust library at https://github.com/asajeffrey/wasm/tree/typechecking-blowup uses more than 10G of memory. The program uses a lot of nested generic traits and lifetime polymorphism. The timing details are:
$ multirust run nightly cargo rustc -- -Z time-passes
Compiling wasm v0.0.1 (file:///home/ajeffrey/github/asajeffrey/wasm)
time: 0.001; rss: 49MB parsing
time: 0.000; rss: 49MB configuration 1
time: 0.000; rss: 49MB recursion limit
time: 0.000; rss: 49MB gated macro checking
time: 0.000; rss: 49MB crate injection
time: 0.003; rss: 54MB macro loading
time: 0.000; rss: 54MB plugin loading
time: 0.000; rss: 54MB plugin registration
time: 0.025; rss: 56MB expansion
time: 0.001; rss: 56MB complete gated feature checking 1
time: 0.007; rss: 56MB configuration 2
time: 0.000; rss: 56MB gated configuration checking
time: 0.003; rss: 56MB maybe building test harness
time: 0.003; rss: 56MB prelude injection
time: 0.000; rss: 56MB checking that all macro invocations are gone
time: 0.000; rss: 56MB checking for inline asm in case the target doesn't support it
time: 0.000; rss: 56MB complete gated feature checking 2
time: 0.000; rss: 56MB const fn bodies and arguments
time: 0.002; rss: 56MB assigning node ids
time: 0.003; rss: 62MB lowering ast -> hir
time: 0.001; rss: 62MB indexing hir
time: 0.000; rss: 62MB attribute checking
time: 0.002; rss: 62MB early lint checks
time: 0.001; rss: 60MB external crate/lib resolution
time: 0.000; rss: 60MB language item collection
time: 0.005; rss: 68MB resolution
time: 0.000; rss: 68MB lifetime resolution
time: 0.000; rss: 68MB looking for entry point
time: 0.000; rss: 68MB looking for plugin registrar
time: 0.001; rss: 69MB region resolution
time: 0.000; rss: 69MB loop checking
time: 0.000; rss: 69MB static item recursion checking
time: 0.003; rss: 71MB type collecting
time: 0.000; rss: 71MB variance inference
time: 0.027; rss: 89MB coherence checking
time: 0.014; rss: 89MB wf checking
time: 0.004; rss: 89MB item-types checking
at which point the process starts using large amounts of time and memory.
The same behaviour happens with nightly-2015-12-01, so this is not part of the recent rewrite of typechecking.
Discussed on irc with @eddyb, @Manishearth and @aturon.
Metadata
Metadata
Assignees
Labels
A-type-systemArea: Type systemArea: Type system
Activity
nikomatsakis commentedon Feb 23, 2016
cc me
Trying newtypes for abbreviations, as a work-around for rust-lang/rus…
nikomatsakis commentedon Feb 24, 2016
On IRC, @asajeffrey posted this self-contained example that exhibits the same phenomena:
asajeffrey commentedon Feb 24, 2016
You beat me to it :) https://play.rust-lang.org/?gist=5183e32b3f0fcdfccf61
asajeffrey commentedon Feb 24, 2016
There is a work-around for this example: https://play.rust-lang.org/?gist=ed22452c4eda71821a6d
Made Upcast a constraint on ToStatic::Static (workaround for rust-lan…
asajeffrey commentedon Feb 25, 2016
Sad to say the work-around doesn't scale up completely. The problem is the interaction between this issue and #30867 (comment).
The work-around for this issue is to make what were type parameters into associated types, the work-around for #30867 (comment) is to turn what were associated types into type parameters. There is a tension here.
asajeffrey commentedon Feb 25, 2016
Chaining iterators has a similar problem: https://play.rust-lang.org/?gist=a0c05fbf5c43234fb7c3
asajeffrey commentedon Feb 25, 2016
A possible work-around for chaining iterators is to distinguish between top-down and bottom-up iterators: https://play.rust-lang.org/?gist=8532619e7f8bae0ffbef
asajeffrey commentedon Feb 25, 2016
Separating out the projection for the iterator from iterator function itself seems to do the trick... https://play.rust-lang.org/?gist=1cf9886dd074e073cd6a
asajeffrey commentedon Mar 1, 2016
I implemented the work-around for parsell. The trick was to separate out bottom-up computation of associated types from their top-down use as type parameters. You can see this, for example, in http://asajeffrey.github.io/parsell/target/doc/parsell/trait.StatefulInfer.html which used to be one trait, but is now given as the union of a trait for bottom-up calculation of an
Outputassociated type http://asajeffrey.github.io/parsell/target/doc/parsell/trait.HasOutput.html, and a trait for top-down use of that type http://asajeffrey.github.io/parsell/target/doc/parsell/trait.Stateful.html.It's a bit round-about, but it does the job of reducing type-checking space/time.
asajeffrey commentedon Mar 1, 2016
The work-around took the compile time for https://github.com/asajeffrey/wasm/tree/9297d84654c74d24f1f8cc0ff96e468a39c12bb2 down from 10G to about 200M. It compiles in about 45 sec, which isn't perfect but is a lot better than never terminating, which is what was happening before.
nikomatsakis commentedon Mar 16, 2016
As part of some work towards lazy normalization, I added a cache to the associated type projection machinery. This achieved a 10x improvement on the test case that @asajeffrey posted a little while back (with two levels of parens added):
nikomatsakis commentedon Mar 16, 2016
Added two more levels of parens and re-ran the test, results:
I hope to improve the cache and it'd be interesting to see if we can bring those numbers down, but obviously this is a big improvement.
asajeffrey commentedon Mar 16, 2016
Yay! Let me know when there's a PR I can play with.
eddyb commentedon Mar 16, 2016
@asajeffrey The commits above suggest there is a branch.
asajeffrey commentedon Mar 16, 2016
@eddyb yes, just waiting for it to settle down before trying it out!
asajeffrey commentedon Mar 16, 2016
And there's now a PR: #32287.
Auto merge of #33816 - nikomatsakis:projection-cache-2, r=arielb1
nikomatsakis commentedon Mar 22, 2017
I think this particular issue is effectively solved for quite some time now. Certainly the examples that @asajeffrey give no longer cause issues in the playpen.