daml/compiler
Moritz Kiefer a178f62613
Fix packaging performance (#6350)
fixes #3150

This PR introduces a patch to GHC to fix the performance of the
pattern match checker in the presence of multiple packages which
is currently significantly (orders of magnitude) slower than having
everything in a single package. I also added a test case that hits
this. Here’s what you need to hit this issue:

1. A typeclass with a functional dependency. `HasField` is the obvious
   candidate for this.

2. A lot of instances of this typeclass in a separate package (this is
   the only part where the separate package matters).

3. A reasonably large ADT with a bunch of strict fields.

4. A pattern match in the context of some constraints of the
   typeclass. The constraints can be completely unused.

In that case, you will get a significant slowdown in the number of
instances, number of constructors and number of constraints (didn’t
verify if it’s linear but it is significant which is all that
matters).

Here’s why this happens:

1. The pattern match checker checks for strict fields if the type is
   inhabited.

2. This calls `pmTopNormaliseType_maybe` to normalize a type (the details don’t
   matter) which in turn calls into the typechecker. This function is
   called very often (presumably linear in the number of constructors
   but didn’t verify.)

3. The typechecker has some logic in `improveFromInstEnv` for
   generating additional equations by unifying functional
   dependencies `a -> b` with constraints in scope
   and thereby deducing information about `b`.

4. In the pattern match checker the list of instances of the home
   package is empty since the pattern match checker (apparently)
   doesn’t actually care about those extra equations. However, the
   list of instances in the EPS is not empty. This is the issue here:
   By moving it to an external package we suddenly end up with
   thousands of instances that we try to unify with the functional
   dependencies every time we normalize which happens very often.

Proposed fix:

The solution is rather simple: Since the pattern match checker
apparently does not care about the instances of the home package, it
almost certainly doesn’t care about instances in general so we just
empty the instances of external packages explicitly.

Is the fix correct?

1. I verified that the GHC test suite passes with this patch which
   gives me a reasonable level of confidence.

2. I verified that our own test suite passes.

3. The most dodgy part is actually emptying the instance since the
   whole EPS stuff is a mutable mess. What could in theory happen is that
   the PM ends up loading an interface file that mutates this
   again. However, afaiu it is impossible for the PM to need an
   interface that the typechecker didnt already need. I did do a bunch
   of debugging and this is exactly what I observed in my experiments.

Alternative ideas and upstreaming:

The other option would be to not try and mess with the EPS but somehow
have a conditional flag somewhere in the typechecker env to disable
this logic in the pattern match checker. However, that sounds
significantly more complex so I don’t think it’s worth the effort.

GHC 8.10 has a new pattern match checker that has different
performance characteristics and seems to do much better here so there
is little reason to try and upstream this. I strongly want to avoid
upgrading DAML to 8.10 at this point (too much risk, let’s wait until
things calm down)

changelog_begin

- [DAML Compiler] Fix an issue where compilation slowed down
  significantly when code was split up into several packages. See
  https://github.com/digital-asset/daml/issues/3150

changelog_end
2020-06-16 15:12:34 +02:00
..
daml-extension update various yarn lock and package json files to resolve security vulnerabilities (#6319) 2020-06-12 11:35:37 -04:00
daml-lf-ast damlc inspect: Add output modes with less details (#6280) 2020-06-10 08:12:07 +00:00
daml-lf-proto Use com.daml as root package (#5343) 2020-04-05 19:49:57 +02:00
daml-lf-reader replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
daml-lf-tools damlc: Run simplifier on templates as well (#6286) 2020-06-15 11:24:25 +00:00
daml-lf-verify damlc: Run simplifier on templates as well (#6286) 2020-06-15 11:24:25 +00:00
daml-licenses replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
damlc Fix packaging performance (#6350) 2020-06-16 15:12:34 +02:00
ghcide Get ghcide from the new upstream repo (#2867) 2019-09-11 08:57:48 +02:00
hie-core Get ghcide from the new upstream repo (#2867) 2019-09-11 08:57:48 +02:00
lsp-tests Turn warnings for module name/record name mismatches into errors (#5266) 2020-03-30 10:21:53 +00:00
repl-service Ledger id requirement (#6323) 2020-06-12 15:00:32 +00:00
scenario-service Ledger: use standard transactions in the indexer (#6297) 2020-06-11 16:12:21 +02:00
README.md open-sourcing daml 2019-04-04 09:33:38 +01:00

DAML Compiler

This directory contains several libraries used by and the executable for the DAML compiler.

Libraries

  • daml-lf-ast: The DAML-LF AST and type checker.