Repository navigation
Handle process deaths without scanning unrelated monitors and connections - #495
Merged
LaurentRDC merged 4 commits intoOct 13, 2026
Merged
Conversation
The cost of a process death should not depend on the monitors and connections of other processes on the node. Measure it with 0, 1,000 and 10,000 of each. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ange ncEffectDied scanned all links and monitors of the node on every death (splitNotif used partitionWithKeyBy1st with impliesDeathOf), for a node death also all watchers, and it rebuilt registeredOnNodes. So each death took time proportional to all monitors and links of the node, and local sends, which also go through the node controller, waited behind it. Add deathKey, a monotone projection of identifiers such that impliesDeathOf a b if and only if deathKey a b is in deathKeys a. The identifiers that die with a are then a few ranges of keys, which the new BiMultiMap.partitionOn finds with Map.spanAntitone in time polylogarithmic in the size of the map, plus the size of the result. ncEffectDied still scans registeredHere, which is keyed by name. In the deaths benchmark, a process death with 10,000 unrelated monitors on the node went from about 2,900 to 45 µs (about 15 µs with none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
cleanupProcess scanned all of localConnections on every process exit. The result is part of the node state, which local and remote sends, spawns and the node controller also use. Connections are keyed by (from, to), so the connections of the process and its typed channels are found with partitionOn and deathKey. In the deaths benchmark, a process death with 10,000 unrelated connections on the node went from about 2,300 to 37 µs (about 15 µs with none). Co-Authored-By: Claude Opus 5.5 <[email protected]>
Contributor
|
For context, @vasdommes and I encountered performance problems with a distributed-process-based scheduler that we have been working on, and this was one of the fixes. |
LaurentRDC
reviewed
Oct 13, 2026
LaurentRDC
left a comment
Member
There was a problem hiding this comment.
Thanks! I mostly have some organizational comments. Nothing showstopping
- Bump distributed-process to 0.7.10, and require it in TestDeathKeys. - Add @SInCE 0.7.10 to the new exports of BiMultiMap and Messaging. - Move IdentifierKind and identifierKind to Messaging, next to deathKey, their only user. Co-Authored-By: Claude Opus 5.5 <[email protected]>
LaurentRDC
approved these changes
Oct 13, 2026
Member
|
Some tests are flaky, I think this is ready to merge. Thanks @vasdommes ! |
LaurentRDC
merged commit Oct 13, 2026
2dc5ada
into
haskell-distributed:master
17 of 20 checks passed
Member
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Handle process deaths without scanning unrelated monitors and connections
Problem
On a node with many monitors, links or connections, each process death took
time proportional to all of them, not only to the ones it affects:
ncEffectDiedpartitioned all links and monitors of the node(
splitNotif), for a node death also all watchers, and it rebuiltregisteredOnNodes.cleanupProcesspartitioned all oflocalConnectionson every process exit.Local sends also go through the node controller, so they wait behind slow
deaths. We found this in a task scheduler built on distributed-process, which
keeps ~1,000 monitors and ~600 connections and runs tens of thousands of
short-lived processes; these changes cut its total run time by ~10–20%.
Change
The identifiers that die with an identifier (see
impliesDeathOf) form at mostthree ranges of keys in the derived
Ordinstances: for a node, the nodeitself, its processes and its typed channels; for a process, the process and
its typed channels.
Internal.Messaging:deathKeyanddeathKeys.deathKey identis amonotone projection, and
impliesDeathOf a bholds if and only ifdeathKey a bis indeathKeys a.Internal.BiMultiMap:partitionOn,partitionOnBy1standpartitionOnBy2nd.partitionOn f ps misMap.partitionWithKey (\k _ -> elem (f k) ps) mfor a monotonef,computed with
Map.spanAntitone.Internal.Types:IdentifierKindandidentifierKind, next tonodeOf.Node:splitNotif, the removal of dead watchers,registeredOnNodesandcleanupProcessuse them.Behaviour does not change, including the order of notifications and of
forwarded deaths. The code relies on the derived
Ordinstances ofIdentifier,ProcessIdandSendPortId; their declarations now say so, andthe new tests check it.
Benchmark
The first commit adds a
deathsgroup to the benchmarks: a process death(spawn, monitor, exit, notification) while the node holds N unrelated
monitors or connections. Time per death, mean of two runs, GHC 9.10.3,
-O2:Differences of a few µs are noise. The remaining growth from 1,000 to 10,000
entries comes from garbage collection of the larger heap: with
+RTS -A64m,both cases take the same time.
To compare, run at the first commit and then at the last one:
Tests
TestDeathKeysin distributed-process-tests:deathKeyagrees withimpliesDeathOf, anddeathKeyis monotone;partitionOn,partitionOnBy1standpartitionOnBy2ndgivethe same results as
Map.partitionWithKey,partitionWithKeyBy1standpartitionWithKeyBy2nd.Notes for reviewers
TestDeathKeysuses functions that are new in this PR. Its lower bound ondistributed-process should become the next release when versions are bumped.
registeredHere, which is keyed by name;closeImplicitReconnections, because connections are keyed byfrom,not
to.🤖 Generated with Claude Code