Skip to content
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

cardano-testnet: Waiting for blocks using EpochStateView. #5836

Closed

Conversation

carbolymer
Copy link
Contributor

@carbolymer carbolymer commented May 10, 2024

Description

This PR provides new functions allowing to extract slot number and block number from epoch state view, and additionally wait for epoch state view updates. This cuts down the test execution time a bit. Waiting for an epoch in a plutus test takes ~70s, where one block wait is around 20s.

This PR is stacked on top of #5835

watchEpochStateUpdate was inspired by @palas 's watchEpochStateUpdate function in #5830 , but it uses TChan for waiting for an update, instead of polling.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. These may include:
    • golden tests
    • property tests
    • roundtrip tests
    • integration tests
      See Runnings tests for more details
  • Any changes are noted in the CHANGELOG.md for affected package
  • The version bounds in .cabal files are updated
  • CI passes. See note on CI. The following CI checks are required:
    • Code is linted with hlint. See .github/workflows/check-hlint.yml to get the hlint version
    • Code is formatted with stylish-haskell. See .github/workflows/stylish-haskell.yml to get the stylish-haskell version
    • Code builds on Linux, MacOS and Windows for ghc-8.10.7 and ghc-9.2.7
  • Self-reviewed the diff

Note on CI

If your PR is from a fork, the necessary CI jobs won't trigger automatically for security reasons.
You will need to get someone with write privileges. Please contact IOG node developers to do this
for you.

@carbolymer carbolymer force-pushed the mgalazyn/test/wait-for-blocks-using-epochstateview branch 3 times, most recently from 14c8e77 to 57828c1 Compare May 13, 2024 14:04
@carbolymer carbolymer marked this pull request as ready for review May 13, 2024 14:08
@carbolymer carbolymer requested a review from a team as a code owner May 13, 2024 14:08
@carbolymer carbolymer changed the title Waiting for blocks using epochstateview Waiting for blocks using EpochStateView. May 13, 2024
@carbolymer carbolymer changed the title Waiting for blocks using EpochStateView. cardano-testnet: Waiting for blocks using EpochStateView. May 13, 2024
@carbolymer carbolymer force-pushed the mgalazyn/test/wait-for-blocks-using-epochstateview branch 2 times, most recently from 5c2bfe4 to 1bbdef6 Compare May 13, 2024 14:12
Copy link
Contributor

@palas palas left a comment

Choose a reason for hiding this comment

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

Nice! This will make tests much simpler. I just added a couple of ideas for small simplifications

@carbolymer carbolymer force-pushed the mgalazyn/test/wait-for-blocks-using-epochstateview branch 3 times, most recently from d52dc11 to eb553cc Compare May 14, 2024 09:33
@carbolymer carbolymer force-pushed the mgalazyn/test/wait-for-blocks-using-epochstateview branch 2 times, most recently from 91a28a8 to 84f3489 Compare May 14, 2024 14:21
@carbolymer carbolymer force-pushed the mgalazyn/test/wait-for-blocks-using-epochstateview branch from 84f3489 to 7e0c341 Compare May 14, 2024 14:40
Copy link
Contributor

@palas palas left a comment

Choose a reason for hiding this comment

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

👍

, socketPath :: !SocketPath
, epochStateView :: !(IORef (Maybe AnyNewEpochState))
-- ^ node socket path, to which foldEpochState is connected to
, wakeLock :: !(TChan ())
Copy link
Contributor

Choose a reason for hiding this comment

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

What was wrong with the IORef? If we are going to use TChans and TMVars there needs to be good justification for doing so. I don't immediately see the benefit of this increased complexity in an already tedious testing environment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal here is to listen to changes of EpochStateView. You can't do this just using IORef. You could do this using MVar, and having watching threads block on empty MVar and continue when MVar gets filled. But then you still need additional IORef for functions checking for current EpochStateView without blocking. The problem with using MVar and IORef at the same time, is that you don't have any guarantees about the order of operations in the listening thread. In other words, If you update IORef and MVar in order in one thread, the other threads may see it in a different order. This means that listeners waiting on MVar () may see stale IORef value.

I've chosen STM which gives you a single view on both of variables, but you don't have MVar analogue for waiting in multiple threads for an update of a single MVar. (TMVar is only single-wakeup).

If we want to avoid STM here, we can define view and lock:

, wakeLock :: !(MVar (AnyNewEpochState, SlotNo, BlockNo))
, epochStateView :: !(IORef (AnyNewEpochState, SlotNo, BlockNo))

assuming we won't use one value to check the other, because they can be out-of-sync.

Copy link
Contributor

@Jimbo4350 Jimbo4350 May 16, 2024

Choose a reason for hiding this comment

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

Why do we need to notify the listeners about changes? I could understand wanting to notify listeners of changes if the changes are short lived but they are not (or at least I can't think of any that are). What problem is this solving? Why specifically do we need this level of granularity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's an alternative to watchEpochStateView which is polling every 100ms EpochStateView. Sometimes new epoch state is updated much slower, like once every few seconds. So it saves some CPU on needlessly computing the check again and again on the same input.

Copy link
Contributor

@Jimbo4350 Jimbo4350 May 16, 2024

Choose a reason for hiding this comment

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

I think the additional complexity is not worth it. We should be using the atomic* versions of the IORef functions to avoid race conditions/partial writes etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But you can't implement blocking and waiting or multi-wakeup using just IORef.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you feel that MVars are too much, I can rewrite this PR using polling in watchEpochStateView.

Copy link
Contributor

@Jimbo4350 Jimbo4350 May 16, 2024

Choose a reason for hiding this comment

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

But you can't implement blocking and waiting or multi-wakeup using just IORef.

Why do we need this? If the goal is to "listen to changes of EpochStateView" and your reason is:

It's an alternative to watchEpochStateView which is polling every 100ms EpochStateView. Sometimes new epoch state is updated much slower, like once every few seconds. So it saves some CPU on needlessly computing the check again and again on the same input.

I say the complexity is not worth it. The changes we are interested in don't require this level of granularity. Saving a little bit of CPU does not justify the additional complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Waiting on MVar is not that much more complex than polling. I'll rewrite the PR using polling then.

Copy link
Contributor

Choose a reason for hiding this comment

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

The one I wrote already uses polling, you can use that one, or tune it

@carbolymer
Copy link
Contributor Author

Superseded by #5843

@carbolymer carbolymer closed this May 16, 2024
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