-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
synchronise churn with outbound governor #4854
Conversation
Stolen from `ouroboros-consensus`.
Effectiveness of
|
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/EstablishedPeers.hs
Show resolved
Hide resolved
mbCounters <- atomically $ do | ||
-- Update counters | ||
counters <- readTVar countersVar | ||
let !counters' = peerSelectionStateToCounters decisionState | ||
if counters' /= counters | ||
then writeTVar countersVar counters' | ||
>> return (Just counters') | ||
else return Nothing | ||
|
||
-- Trace counters | ||
traverse_ (traceWith countersTracer) mbCounters | ||
|
||
traverse_ (traceWith tracer) decisionTrace | ||
traceWithCache countersTracer | ||
(countersCache decisionState) | ||
newCounters | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could rethink how we trace these things. Overall, if my understanding is correct, each decision changes only a few things in the state, but here it looks like we re-compute everything to trace. Maybe we could recompute only the things that did change in this step, and the tracer could take the parts that did not change and add those parts that we had to re-calculate.
Maybe this could be a separate issue, since the patch looks correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we don't know which things have changed, so we'll need to recompute them anyway. But maybe there's something clever I am missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just thinking out loud, but maybe the job/monitoring action that records a change could return some sort of lens that references which fields it has touched, along with the entire counters record (most of which would remain unevaluated). Then code here could apply this lens to left and right hand sides just to see if there is indeed a difference, and also use the lens to update just the changed counters in countersVar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A fancy idea: we could use NoThunks
(or its approach) to build a monoid that combines two records, picking the evaluated thunks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have quite a few relationships between PeerSelectionCounters
record fields which we'd need to preserve to really avoid recomputing things. This would require some fancy machine to derive the right instance - might be a nice challenge. Here's a basic idea which seems to work when there are no dependencies between fields.
Testing also will be non trivial, because constructed record will not be without thunks (no NoThunks
cannot be used), simply because this will require Generics
and to
will leave us with fields which are thunks themselves (although they will point to computed values).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, I don't think that the nothunks
approach is something we'd like to include in production because it relies on unsafePerformIO
and some rather fancy GHC
runtime API. If we have a performance regression which cannot be accepted, we'll look into how to cache part of the data structure as you propose. I hope that this won't be a problem because these structures are rather small (e.g. less than 1000 entries and in standard configuration even less than 100).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method you propose is very clever, but as you say maybe it won't be a problem. We could create a separate issue to perform some benchmarks to convince ourselves that the impact is indeed negligible, otherwise we can try to resolve it separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouroboros-network-testing/src/Ouroboros/Network/Testing/Utils.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
ouroboros-network/src/Ouroboros/Network/PeerSelection/Governor/Types.hs
Outdated
Show resolved
Hide resolved
`PeerSelectionCounters` provide now raw data in terms of sizes of active / established / known sets. Added `PeerSelectionCountersHWC` pattern synonym, which calculates sizes in terms of hot / warm / cold sets. The counters include: * public roots (excluding big ledger peers) * big ledger peers * bootstrap peers * local roots * shared peers (e.g. peers received through peer sharing) Co-authored-by: Armando Santos (@bolt12) Co-authored-by: Marcin Szamotulski (@coot)
Also export it from `Governor` module, it is useful in `cardano-node`.
`localRoots` didn't count local connections, but the targets. We don't expose other targets in EKG metrics, so there's no reason to actually include local root targets.
Since `PeerSelectionCounters` are stored in a `TVar` we don't need to cache them in `PeerSelectionState`.
Use `peerSelectionStateToCounters` to compute numbers of peers over which outbound-governor is making decisions.
Local roots are always disjoint with big ledger peers. This is ensured when we are adding new big ledger peers and when the local roots has changed, there's no need to subtract them in `EstablishedPeers.aboveTargetOther`.
PeerSelectionView is a generalisation of PeerSelectionCounters useful internally in the outbound-governor. It allows us to not duplicate the logic of computing counters separately for churn and the outbound governor, which can help us to introduce bugs.
`Ouroboros.Network.PeerSelection.Governor.Type` excluded from `check-stylish`, to preserve large export of record names in pattern synonyms.
flake.nix: set -Werror GHC option for all project packages
testing-utils: added set properties
policies: declare {min,max}ChainSyncTimeout in the policies module
peer-selection: extended PeerSelectionCounters
churn: implemented explicit synchronisation
churn: added two simple testnet tests
peer-selection-tests: order imports
peer-selection: renamed peerStateToCounters
peer-selection: removed localRoots from counters
peer-selection: removed counters cached
churn: added ChurnCounters tracer
peer-selection: use HasCallStack where pickPeers is used
peer-selection: use peerSelectionStateToCounters
peer-selection: remove not needed subtraction
peer-selection: introduced PeerSelectionView
check-stylish: added ignore file
Branch
Pull Request