Skip to content

Conversation

@mitchellwrosen
Copy link
Contributor

@mitchellwrosen mitchellwrosen commented Aug 15, 2025

Overview

This PR bumps the Unison dependency and integrates the new merge API, which is simpler and includes a "narrowing" step that allows us to avoid hydrating terms and types whose synhashes can't be different. This makes computing a namespace diff much more efficient, in the common case that most definitions are are not changed (where "changed" includes propagated updates).

This PR also optimizes a few other things related to computing and storing a namespace diff:

  • Propagated changes are no longer included in a diff, at all. We can add something back when we intend to render something (e.g. "123 dependents received propagated updates" or something), but for now, these diffs were adding a lot of runtime to calculating a diff, since we computed a two-way term diff for every single propagated change.
  • I optimized a few aspects of the post-diff database queries we perform in order to munge the diff into a JSON blob for the front end. Essentially, we now perform fewer, smaller queries, and reuse data that we already fetched during computing the diff, which we weren't doing before.

Some performance numbers from staging:

  • On trunk, it takes about 36 seconds to get a diff for a single addition to @unison/base, and 48 seconds to get a diff for a single update that has about 1000 transitive dependents.
  • On this branch, both are essentially instantaneous to a user (the diff was there by the time I clicked into it).

Next steps: I think it would be possible to further cut down on query times by batching better, if we want to pursue even faster diffs.

Note: don't merge yet! Plan: review this, then merge the Unison PR, then bump this PR's Unison dependency to point at that commit.

@mitchellwrosen mitchellwrosen marked this pull request as ready for review August 25, 2025 18:36
@mitchellwrosen mitchellwrosen requested a review from a team as a code owner August 25, 2025 18:36
Comment on lines 200 to 206
expectTypeDeclsByRefIdsOf ::
(QueryM m) =>
CodeCache scope ->
Traversal s t TypeReferenceId (V1.Decl Symbol Ann) ->
s ->
m t
expectTypeDeclsByRefIdsOf codeCache@(CodeCache {codeCacheCodebaseEnv}) trav s = do
Copy link
Member

@ChrisPenner ChrisPenner Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of just calling directly into getTypeDeclsByRefIdsOf then unwrapping the Maybes into an error rather than copying the implementation? I think it'd make it easier to update these methods in the future :)

Same for the terms methods

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems fine; the inner database calls here are:

  • Codebase.loadV1TypeDeclarationsByRefIdsOf : Id -> Maybe Decl
  • Codebase.expectTypeDeclarationsByRefIdsOf : Id -> Decl

so if we don't want to have a variant at the code cache level for an underlying call to Codebase.expectTypeDeclarationsByRefIdsOf, then we do have do duplicate the error it throws when a decl is missing. That is only a tiny amount of duplication, though. Still in favor of doing that instead of what's currently in the PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah a duplicate error message sounds fine, but avoiding duplicating the whole function would be worthwhile :)

@ChrisPenner
Copy link
Member

ChrisPenner commented Aug 26, 2025

I ran some local tests:

  • changed a doc on a single definition with no dependents, this was very fast, basically just the cost of loading all the names into memory, which ideally we'd somehow avoid but I'm not sure what they're currently being used for.
  • changed data.list.map, looks like the bottleneck here is actually building the pretty-printer:
image

@ChrisPenner ChrisPenner merged commit 97f3c52 into main Sep 2, 2025
4 checks passed
@ChrisPenner ChrisPenner deleted the narrow branch September 2, 2025 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants