daml/ci
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
..
azure-cleanup replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
cron update for no stack-tracing in speedy perf (#6363) 2020-06-16 11:36:05 +00:00
da-ghc-lib Fix packaging performance (#6350) 2020-06-16 15:12:34 +02:00
docker/daml-sdk Add /etc/nsswitch.conf to our Dockerfile (#5882) 2020-05-07 09:44:44 +02:00
patch_bazel_windows Sort files when calculating CACHE_KEY (#6173) 2020-05-31 22:02:13 +02:00
build-unix.yml Use Sandbox Classic as DAML on SQL (#6095) 2020-05-27 08:31:27 +02:00
build-windows.yml trigger all releases from master (#6016) 2020-05-19 19:18:10 +02:00
check-changelog.sh enable patch releases (#5584) 2020-04-16 17:50:55 +02:00
compatibility_ts_libs.yml Include create-daml-app tests in compatibility tests (#5945) 2020-05-13 10:39:51 +02:00
compatibility-windows.yml Include create-daml-app tests in compatibility tests (#5945) 2020-05-13 10:39:51 +02:00
compatibility.yml Include create-daml-app tests in compatibility tests (#5945) 2020-05-13 10:39:51 +02:00
configure-bazel.sh Increment Windows cache URL (#6321) 2020-06-12 15:33:38 +02:00
daily_tell_slack.yml fix error message on daily compat failure (#6337) 2020-06-14 22:52:57 +02:00
dev-env-install.sh replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
dev-env-push.py replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
postgresql.conf CI: Run PostgreSQL once for all Scala tests. (#5919) 2020-05-14 09:06:34 +02:00
report-end.yml replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
report-start.yml replace DAML Authors with DA in copyright headers (#5228) 2020-03-27 01:26:10 +01:00
slack_user_ids Notify Sofia on #team-daml-ci (#5487) 2020-04-08 09:31:54 +00:00
tell-slack-failed.yml fix tell-slack-failed CI "function" (#5670) 2020-04-22 15:21:04 +02:00
windows-diagnostics.ps1 windows: CI agent diagnostics (#1146) 2019-05-15 11:59:56 +02:00