-
Notifications
You must be signed in to change notification settings - Fork 100
Start of work on removing re-exports #2279
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
base: master
Are you sure you want to change the base?
Conversation
Transaction costsSizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using
Script summary
|
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 5836 | 10.59 | 3.36 | 0.52 |
| 2 | 6037 | 12.25 | 3.87 | 0.54 |
| 3 | 6238 | 14.48 | 4.58 | 0.57 |
| 5 | 6641 | 18.43 | 5.81 | 0.63 |
| 10 | 7647 | 28.90 | 9.10 | 0.79 |
| 43 | 14279 | 98.58 | 30.79 | 1.80 |
Commit transaction costs
This uses ada-only outputs for better comparability.
| UTxO | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 556 | 2.44 | 1.16 | 0.20 |
| 2 | 743 | 3.38 | 1.73 | 0.22 |
| 3 | 922 | 4.36 | 2.33 | 0.24 |
| 5 | 1283 | 6.41 | 3.60 | 0.28 |
| 10 | 2176 | 12.13 | 7.25 | 0.40 |
| 54 | 10072 | 98.61 | 68.52 | 1.88 |
CollectCom transaction costs
| Parties | UTxO (bytes) | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|---|
| 1 | 57 | 525 | 24.42 | 7.12 | 0.42 |
| 2 | 113 | 636 | 32.24 | 9.37 | 0.51 |
| 3 | 170 | 747 | 41.46 | 11.98 | 0.60 |
| 4 | 226 | 862 | 53.70 | 15.30 | 0.73 |
| 5 | 282 | 969 | 64.26 | 18.20 | 0.84 |
| 6 | 338 | 1081 | 63.93 | 18.54 | 0.85 |
| 7 | 393 | 1192 | 86.99 | 24.54 | 1.08 |
| 8 | 451 | 1303 | 80.12 | 23.15 | 1.02 |
Cost of Increment Transaction
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 1794 | 24.37 | 7.71 | 0.48 |
| 2 | 2003 | 26.87 | 9.07 | 0.52 |
| 3 | 2060 | 26.86 | 9.75 | 0.53 |
| 5 | 2448 | 32.33 | 12.60 | 0.61 |
| 10 | 3285 | 43.71 | 19.13 | 0.79 |
| 39 | 7635 | 98.82 | 53.75 | 1.67 |
Cost of Decrement Transaction
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 626 | 22.80 | 7.39 | 0.42 |
| 2 | 703 | 22.58 | 7.95 | 0.42 |
| 3 | 962 | 26.61 | 9.77 | 0.48 |
| 5 | 1145 | 28.07 | 11.48 | 0.51 |
| 10 | 2009 | 38.31 | 17.69 | 0.68 |
| 41 | 6737 | 99.67 | 55.42 | 1.65 |
Close transaction costs
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 657 | 29.09 | 8.89 | 0.48 |
| 2 | 838 | 31.69 | 10.29 | 0.52 |
| 3 | 955 | 30.98 | 10.76 | 0.52 |
| 5 | 1282 | 37.73 | 13.99 | 0.61 |
| 10 | 2199 | 46.27 | 19.80 | 0.76 |
| 36 | 6000 | 97.61 | 51.49 | 1.57 |
Contest transaction costs
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 679 | 33.83 | 10.16 | 0.53 |
| 2 | 874 | 36.52 | 11.59 | 0.57 |
| 3 | 899 | 37.20 | 12.40 | 0.58 |
| 5 | 1274 | 42.53 | 15.25 | 0.66 |
| 10 | 2058 | 54.35 | 21.90 | 0.84 |
| 28 | 4899 | 97.34 | 45.88 | 1.48 |
Abort transaction costs
There is some variation due to the random mixture of initial and already committed outputs.
| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|
| 1 | 5810 | 27.08 | 9.08 | 0.69 |
| 2 | 5920 | 34.75 | 11.63 | 0.78 |
| 3 | 5903 | 37.12 | 12.31 | 0.80 |
| 4 | 6359 | 55.85 | 18.86 | 1.02 |
| 5 | 6530 | 63.85 | 21.63 | 1.11 |
| 6 | 6662 | 71.82 | 24.22 | 1.20 |
| 7 | 6762 | 83.47 | 28.18 | 1.33 |
| 8 | 6894 | 92.40 | 31.06 | 1.42 |
FanOut transaction costs
Involves spending head output and burning head tokens. Uses ada-only UTXO for better comparability.
| Parties | UTxO | UTxO (bytes) | Tx size | % max Mem | % max CPU | Min fee ₳ |
|---|---|---|---|---|---|---|
| 10 | 0 | 0 | 5835 | 18.93 | 6.32 | 0.61 |
| 10 | 5 | 285 | 6004 | 30.16 | 10.71 | 0.74 |
| 10 | 10 | 568 | 6173 | 39.69 | 14.52 | 0.85 |
| 10 | 20 | 1141 | 6515 | 60.42 | 22.68 | 1.09 |
| 10 | 30 | 1709 | 6855 | 80.04 | 30.46 | 1.32 |
| 10 | 39 | 2222 | 7162 | 98.49 | 37.73 | 1.53 |
End-to-end benchmark results
This page is intended to collect the latest end-to-end benchmark results produced by Hydra's continuous integration (CI) system from the latest master code.
Please note that these results are approximate as they are currently produced from limited cloud VMs and not controlled hardware. Rather than focusing on the absolute results, the emphasis should be on relative results, such as how the timings for a scenario evolve as the code changes.
Generated at 2025-09-26 11:02:23.63790435 UTC
Baseline Scenario
| Number of nodes | 1 |
|---|---|
| Number of txs | 300 |
| Avg. Confirmation Time (ms) | 5.251245556 |
| P99 | 7.787443809999988ms |
| P95 | 6.4171106ms |
| P50 | 5.0353455ms |
| Number of Invalid txs | 0 |
Memory data
| Time | Used | Free |
|---|---|---|
| 2025-09-26 11:01:03.286889332 UTC | 1317M | 6867M |
| 2025-09-26 11:01:04.270766457 UTC | 1361M | 6787M |
| 2025-09-26 11:01:05.270753831 UTC | 1430M | 6645M |
| 2025-09-26 11:01:06.270861161 UTC | 1452M | 6622M |
| 2025-09-26 11:01:07.270730767 UTC | 1456M | 6615M |
| 2025-09-26 11:01:08.270854495 UTC | 1462M | 6604M |
| 2025-09-26 11:01:09.270863389 UTC | 1462M | 6604M |
| 2025-09-26 11:01:10.270846668 UTC | 1462M | 6604M |
| 2025-09-26 11:01:11.270810545 UTC | 1462M | 6604M |
| 2025-09-26 11:01:12.27078601 UTC | 1466M | 6600M |
| 2025-09-26 11:01:13.270801446 UTC | 1466M | 6600M |
| 2025-09-26 11:01:14.270857619 UTC | 1466M | 6600M |
| 2025-09-26 11:01:15.270757423 UTC | 1466M | 6600M |
| 2025-09-26 11:01:16.270867553 UTC | 1466M | 6600M |
| 2025-09-26 11:01:17.270878642 UTC | 1466M | 6600M |
| 2025-09-26 11:01:18.270845021 UTC | 1466M | 6600M |
| 2025-09-26 11:01:19.270855892 UTC | 1466M | 6600M |
| 2025-09-26 11:01:20.270760094 UTC | 1466M | 6600M |
| 2025-09-26 11:01:21.270849933 UTC | 1466M | 6599M |
| 2025-09-26 11:01:22.270887251 UTC | 1466M | 6599M |
| 2025-09-26 11:01:23.270811459 UTC | 1466M | 6599M |
| 2025-09-26 11:01:24.270865855 UTC | 1466M | 6599M |
| 2025-09-26 11:01:25.270771771 UTC | 1466M | 6599M |
| 2025-09-26 11:01:26.270854813 UTC | 1466M | 6598M |
| 2025-09-26 11:01:27.270842962 UTC | 1466M | 6598M |
| 2025-09-26 11:01:28.270847384 UTC | 1468M | 6596M |
| 2025-09-26 11:01:29.270775255 UTC | 1468M | 6596M |
| 2025-09-26 11:01:30.270723689 UTC | 1469M | 6596M |
Three local nodes
| Number of nodes | 3 |
|---|---|
| Number of txs | 900 |
| Avg. Confirmation Time (ms) | 40.203484143 |
| P99 | 67.16986677999999ms |
| P95 | 58.02877994999999ms |
| P50 | 39.0445265ms |
| Number of Invalid txs | 0 |
Memory data
| Time | Used | Free |
|---|---|---|
| 2025-09-26 11:01:41.70113294 UTC | 1366M | 6735M |
| 2025-09-26 11:01:42.701121048 UTC | 1366M | 6735M |
| 2025-09-26 11:01:43.701025807 UTC | 1381M | 6720M |
| 2025-09-26 11:01:44.70112016 UTC | 1555M | 6467M |
| 2025-09-26 11:01:45.701094862 UTC | 1567M | 6454M |
| 2025-09-26 11:01:46.702011019 UTC | 1597M | 6424M |
| 2025-09-26 11:01:47.702616369 UTC | 1627M | 6389M |
| 2025-09-26 11:01:48.701906479 UTC | 1653M | 6353M |
| 2025-09-26 11:01:49.704228284 UTC | 1672M | 6324M |
| 2025-09-26 11:01:50.702509567 UTC | 1683M | 6302M |
| 2025-09-26 11:01:51.702123426 UTC | 1687M | 6289M |
| 2025-09-26 11:01:52.70253053 UTC | 1688M | 6281M |
| 2025-09-26 11:01:53.701942327 UTC | 1705M | 6257M |
| 2025-09-26 11:01:54.704955742 UTC | 1714M | 6241M |
| 2025-09-26 11:01:55.701709691 UTC | 1730M | 6218M |
| 2025-09-26 11:01:56.702655284 UTC | 1734M | 6206M |
| 2025-09-26 11:01:57.702110778 UTC | 1740M | 6193M |
| 2025-09-26 11:01:58.701070943 UTC | 1747M | 6178M |
| 2025-09-26 11:01:59.70114752 UTC | 1768M | 6150M |
| 2025-09-26 11:02:00.7010623 UTC | 1768M | 6149M |
| 2025-09-26 11:02:01.701021526 UTC | 1768M | 6149M |
| 2025-09-26 11:02:02.701053661 UTC | 1768M | 6149M |
| 2025-09-26 11:02:03.701045735 UTC | 1768M | 6149M |
| 2025-09-26 11:02:04.701141372 UTC | 1768M | 6149M |
| 2025-09-26 11:02:05.701079454 UTC | 1768M | 6149M |
| 2025-09-26 11:02:06.701179164 UTC | 1767M | 6149M |
| 2025-09-26 11:02:07.701192415 UTC | 1768M | 6148M |
| 2025-09-26 11:02:08.701052029 UTC | 1768M | 6148M |
| 2025-09-26 11:02:09.701069889 UTC | 1768M | 6148M |
| 2025-09-26 11:02:10.701060835 UTC | 1768M | 6148M |
| 2025-09-26 11:02:11.701064589 UTC | 1767M | 6148M |
| 2025-09-26 11:02:12.701119786 UTC | 1767M | 6148M |
| 2025-09-26 11:02:13.701183639 UTC | 1767M | 6148M |
| 2025-09-26 11:02:14.701065177 UTC | 1767M | 6148M |
| 2025-09-26 11:02:15.701112894 UTC | 1767M | 6148M |
| 2025-09-26 11:02:16.701167229 UTC | 1767M | 6148M |
| 2025-09-26 11:02:17.701189981 UTC | 1767M | 6148M |
| 2025-09-26 11:02:18.701061769 UTC | 1767M | 6148M |
| 2025-09-26 11:02:19.701101722 UTC | 1766M | 6148M |
| 2025-09-26 11:02:20.701088095 UTC | 1766M | 6147M |
| 2025-09-26 11:02:21.701071864 UTC | 1771M | 6142M |
| 2025-09-26 11:02:22.701110393 UTC | 1771M | 6142M |
Transaction cost differencesNo cost or size differences found |
e9389c4 to
c49939f
Compare
c49939f to
cf713c1
Compare
ch1bo
left a comment
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.
I'm not sure I understand what specifically caused issues. Can you point me to 1-2 examples changes in cardano-api that are problematic for hydra-cardano-api (and its usage)?
| , blockfrost-client >=0.9.2.0 | ||
| , cardano-api | ||
| , http-conduit | ||
| , hydra-cardano-api |
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 whole intention of hydra-cardano-api is to insulate this (and other packages) from changes in cardano-api. By depending on both, the purpose of depending on hydra-cardano-api is moot and we should switch in full.
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.
I think the idea of hydra-cardano-api just indiscriminately re-exporting large piles of stuff from cardano-api and cardano-ledger is highly flawed. I would also predict that it would cause more problems in the long term than whatever convenience it provides in the short term
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.
@ch1bo We should switch in full and upstream what we can.
The one thing that this library does do that can be considered an end-user assurance are the invariants forall era. era ~ ConwayEra and forall plutusVersion. plutusVersion ~ PlutusV3.
This claim is fine, and a library that is scoped to that guarantee is not objectionable. (And that work is here https://github.com/cardano-scaling/cardano-api-latest) I don't mind either way on that issue.
What is not helping us here is arbitrarily passthrough of these modules, especially as some of these things contain type class instances, and others come from interfaces that are intended to be used qualified. Cardano.Api.UTxO is upstreamed now and there are also 6 or so other user-facing modules in cardano-api now besides the main one Cardano.Api that I think would also benefit from being imported qualified. Transitively importing those is just going to create collisions.
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.
So you say we should depend on cardano-api-latest only? I'm fine with anything and just want to point out that depending on both cardano-api and hydra-cardano-api is not a good idea (because this then makes it even further unclear where things come from).
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 still import cardano-api as cardano-api-latest would only reexport synonyms and wouldn't re-export Cardano.Api.UTxO for example. Qualification could be good here i.e Latest.Era Latest.TxBody etc.
| genericCoverTable, | ||
| pickBlind, | ||
| module Test.Hspec, | ||
| module Test.Hspec.QuickCheck, |
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.
This Test.Hydra.Prelude is following ADR8 to shorten import lists (of test modules in this case). For example on this diff are 101 mentions of "import Test.Hspec", mostly about added imports. Whats the rationale for this change? How are you suggesting to change ADR8?
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.
@locallycompact would be looking for your thoughts here :)
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.
I removed those re-exports as a test case for the removal of large and more difficult re-exports. I wanted to see how easy it was to remove those particular re-exports from this code base. I wanted to start small before I went on to bigger things.
I think they should be removed. I am not going to die on that hill.
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.
I personally think all re-exports should be removed, preludes included. I will refer to all things of this sort as "implicit imports", so this logic applies to both the prelude and hydra-cardano-api both.
I would supercede ADR8 in the following way, briefly:
Implicit imports compete for space in the developer's working memory. A new contributor who did not write the prelude will not be aware of what is re-exported there, and will instinctively use the familiar option e.g BS.writeFile as opposed to writeFileBS.
Implicit imports compete with -Wmissing-import-lists, which is a useful forensic tool in Haskell for identifying the ultimate source of a symbol and controlling it's scope. -Wmissing-import-lists is activated by default in hydra-coding-standards-0.7.0 because it is very helpful for gaining familiarity with new code.
Implicit imports also obscure when a library can be easily mutualised. If we end up with, as we have in the past, collections of related functionality that can be upstreamed to an library that is not strictly dependent on hydra, then we gain the benefit of mutual interest from contributors in that functionality specifically. When we have implicit symbols it is not obvious what libraries would actually be needed to execute that.
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.
Then propose a change or supersede ADR8 along with the change in the code how it would turn out.
Not sure what your proposal would say about NoImplicitPrelude which is currently set for all our packages and the rationale which Prelude is acceptable / what makes base better than relude, cardano-prelude, hydra-prelude... or whether you suggest to import everything explicit always? I'm personally a big fan of explicit imports, but hundreds of lines of Data.Eq, Text.Show, GHC.Generics, Control.Monad, etc. not so much anymore.
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.
I'm sympathic to NoImplicitPrelude for really standard Preludes like relude and RIO etc and for the Control.Monad spam, and it has been mentioned to the GHC developers in the past that there should be a way to make this one principled exception for -Wmissing-import-lists. I could check on the status of that. My preference is still to yield to -Wmissing-import-lists.
On branch GHC gives adequate explanation of which type has and overlapping typeclass instance, but nothing about where those typeclass instances are defined. Due to the heavy resuse of re=exporting of modules external to this package, figuring out where the overlapping instances are coming from is rather difficult. Since the instances are defined elsewhere (probably Re-exporting with a package is always fine, it helps define the API for that package, Re-exporting types and functions, even from outside the package is usually fine. Re-exporting whole modules from external packages is will include re-exporting type class instances. Haskell provides very good techniques for controlling the importing of types and functions (eg explicit and qualitifed imports) but very poor control over importing typoclass instances. Re-exporting of for external packages is usually considered a bad idea. |
|
We really have to get rid of this as early as possible. This is a complete nightmare to deal with. I am currently dealing with dozens of errors like this. |
The fact that
Hydra/Cardano.Apiand other modules were re-exporting large chunks ofcardano-apiandcardano-ledgerwas causing significant problems when moving to a more recent version ofcardano-api.Re-exporting things from one module to another in the same package is never a problem.
Re-exporting simple basic type (eg
ByteStringor Text` is rarely a problem.Re-export whole modules from outside the current package is a really bad idea, especially where typeclass instances are involved. While Haskell provides good tools to control the visibility of types and functions, there is almost zero control of the visibility of typeclass instance. There is no way to stop them being exported from or imported into a module. If two packages both export an instance for a specific type and modules need to be imported from both packages, there is no way to control which instance is visible.
There are a handful of TODOs that can probably only be addressed after the removal of re-exports is complete.