Skip to content

Fix memory leak when loading state from disk#1920

Merged
noonio merged 2 commits intomasterfrom
bounded-memory-loading-state
Mar 31, 2025
Merged

Fix memory leak when loading state from disk#1920
noonio merged 2 commits intomasterfrom
bounded-memory-loading-state

Conversation

@ch1bo
Copy link
Copy Markdown
Member

@ch1bo ch1bo commented Mar 28, 2025

We have a memory (space leak) when loading state files with many transactions.

This is due to a thunk being built up by repeatedly calling aggregate and not forcing allTxs throughout the initial load from disk.

For example, loading 2GB of state on master with a hydra-node invocation that exists after loading state due to mismatched parties -> ~1GB max memory usage:

 151,712,666,608 bytes allocated in the heap
  14,411,335,656 bytes copied during GC
     973,747,296 bytes maximum residency (53 sample(s))
      24,460,192 bytes maximum slop
            2033 MiB total memory in use (0 MiB lost due to fragmentation)

master-heap

With changes from this PR -> 12MB max memory usage:

 152,039,750,336 bytes allocated in the heap
  17,318,725,168 bytes copied during GC
      12,855,112 bytes maximum residency (2268 sample(s))
         246,256 bytes maximum slop
              47 MiB total memory in use (0 MiB lost due to fragmentation)

strictdata-heap


  • CHANGELOG updated or not needed
  • Documentation updated or not needed
  • Haddocks updated or not needed
  • No new TODOs introduced or explained herafter

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 28, 2025

Transaction cost differences

Script summary

Name Size (Bytes)
νInitial -
νCommit -
νHead -
μHead -
νDeposit -

Init transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
40 - - - -

Commit transaction costs

UTxO Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
54 - - - -

CollectCom transaction costs

Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
1 - - - - -
2 - - - - -
3 - - - - -
4 - - - - -
5 - - - - -
6 - - - - -
7 - - - - -
8 - - - - -

Cost of Increment Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 - $${\color{green}-0.39}$$ $${\color{green}-0.09}$$ -
2 - - - -
3 - +0.39 +0.09 -
5 - - - -
10 - - - -
37 - $${\color{green}-0.39}$$ $${\color{green}-0.09}$$ -

Cost of Decrement Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
40 - - - -

Close transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
34 - - - -

Contest transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
27 - - - -

FanOut transaction costs

UTxO, Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
(0, 10) - - - - -
(1, 10) - - - - -
(5, 10) - - - - -
(10, 10) - - - - -
(20, 10) - - - - -
(37, 10) - - - - -

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 28, 2025

Transaction costs

Sizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using arbitrary values and results are not fully deterministic and comparable to previous runs.

Metadata
Generated at 2025-03-31 14:31:21.765434362 UTC
Max. memory units 14000000
Max. CPU units 10000000000
Max. tx size (kB) 16384

Script summary

Name Hash Size (Bytes)
νInitial c8a101a5c8ac4816b0dceb59ce31fc2258e387de828f02961d2f2045 2652
νCommit 61458bc2f297fff3cc5df6ac7ab57cefd87763b0b7bd722146a1035c 685
νHead 0e35115a2c7c13c68ecd8d74e4987c04d4539e337643be20bb3274bd 14756
μHead 57166715eadb8d3135964325c016eea546c21e1c0aae974ca67df9a5* 5541
νDeposit ae01dade3a9c346d5c93ae3ce339412b90a0b8f83f94ec6baa24e30c 1102
  • The minting policy hash is only usable for comparison. As the script is parameterized, the actual script is unique per head.

Init transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 6094 11.41 3.57 0.54
2 6292 13.47 4.19 0.57
3 6493 15.37 4.76 0.59
5 6898 20.19 6.25 0.66
10 7904 31.40 9.68 0.82
40 13936 98.18 30.14 1.77

Commit transaction costs

This uses ada-only outputs for better comparability.

UTxO Tx size % max Mem % max CPU Min fee ₳
1 561 2.44 1.16 0.20
2 740 3.38 1.73 0.22
3 920 4.36 2.33 0.24
5 1279 6.41 3.60 0.28
10 2163 12.13 7.25 0.40
54 10062 98.61 68.52 1.88

CollectCom transaction costs

Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
1 57 529 25.64 7.39 0.43
2 112 636 34.88 9.99 0.53
3 169 747 43.39 12.40 0.62
4 225 858 56.31 15.86 0.76
5 284 969 60.75 17.37 0.81
6 340 1081 73.01 20.66 0.94
7 393 1192 81.37 23.23 1.03
8 452 1303 84.30 24.19 1.06

Cost of Increment Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 1798 25.42 8.31 0.49
2 1990 27.83 9.82 0.53
3 2177 30.33 11.34 0.57
5 2500 34.70 14.08 0.64
10 3230 43.74 20.30 0.79
37 7025 94.36 54.23 1.61

Cost of Decrement Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 603 23.99 7.61 0.43
2 816 26.73 9.04 0.47
3 823 25.43 9.31 0.46
5 1254 31.83 12.42 0.55
10 1867 39.87 17.96 0.68
39 6274 99.54 53.75 1.62

Close transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 635 28.49 8.90 0.47
2 785 32.89 10.94 0.53
3 971 35.49 12.49 0.57
5 1298 39.98 15.29 0.64
10 2016 47.08 20.88 0.77
35 5790 99.93 54.70 1.61

Contest transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 662 35.95 11.00 0.55
2 769 37.49 12.02 0.57
3 1006 41.02 13.95 0.63
5 1359 46.61 17.16 0.71
10 2046 57.99 23.99 0.88
26 4644 98.22 47.70 1.49

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 5975 28.33 9.33 0.71
2 6101 37.52 12.37 0.81
3 6214 46.58 15.35 0.91
4 6326 56.08 18.45 1.01
5 6484 66.01 21.85 1.13
6 6522 71.29 23.42 1.18
7 6695 82.55 27.27 1.31
8 6838 95.37 31.41 1.45

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 6092 20.78 6.84 0.64
10 1 57 6126 20.87 6.98 0.64
10 5 285 6261 30.77 10.75 0.75
10 20 1138 6769 62.72 23.14 1.12
10 30 1705 7108 83.57 31.25 1.36
10 37 2104 7346 98.94 37.19 1.54

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-03-31 14:34:21.503012943 UTC

Baseline Scenario

Number of nodes 1
Number of txs 300
Avg. Confirmation Time (ms) 4.787077476
P99 8.534005379999998ms
P95 6.01781905ms
P50 4.341736ms
Number of Invalid txs 0

Memory data

Time Used Free
2025-03-31 14:33:04.688439322 UTC 890M 6084M
2025-03-31 14:33:09.688224104 UTC 1000M 5943M
2025-03-31 14:33:14.688057537 UTC 1001M 5941M
2025-03-31 14:33:19.688083691 UTC 1017M 5925M
2025-03-31 14:33:24.688138437 UTC 1019M 5922M
2025-03-31 14:33:29.6881305 UTC 1020M 5921M

Three local nodes

Number of nodes 3
Number of txs 900
Avg. Confirmation Time (ms) 28.108149841
P99 43.891000819999995ms
P95 38.0685118ms
P50 26.9042465ms
Number of Invalid txs 0

Memory data

Time Used Free
2025-03-31 14:33:43.601713823 UTC 915M 6035M
2025-03-31 14:33:48.601846628 UTC 1192M 5757M
2025-03-31 14:33:53.602502726 UTC 1255M 5637M
2025-03-31 14:33:58.601910553 UTC 1258M 5581M
2025-03-31 14:34:03.601735039 UTC 1259M 5579M
2025-03-31 14:34:08.601892865 UTC 1261M 5576M
2025-03-31 14:34:13.602040137 UTC 1263M 5574M
2025-03-31 14:34:18.601862557 UTC 1268M 5569M

@ch1bo
Copy link
Copy Markdown
Member Author

ch1bo commented Mar 28, 2025

Without the strictness annotation I could narrow in the leak happening here:

{ allTxs = allTxs <> fromList [(txId tx, tx)]

and here:

https://github.com/cardano-scaling/hydra/tree/ae653e701d1c4023ebb8713318ce48b175f0cb0e/hydra-node/src/Hydra/HeadLogic.hs#L1530

@ch1bo ch1bo self-assigned this Mar 28, 2025
@ch1bo ch1bo moved this from Triage 🏥 to In review 👀 in ☕ Hydra Team Work Mar 28, 2025
@ch1bo ch1bo added this to the 0.21.0 milestone Mar 28, 2025
@ch1bo ch1bo linked an issue Mar 28, 2025 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@noonio noonio left a comment

Choose a reason for hiding this comment

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

Excellent.

In the PR description, could you say how you computed those graphs? Very useful to know!

@noonio noonio force-pushed the bounded-memory-loading-state branch from ae653e7 to c939023 Compare March 31, 2025 14:27
@noonio noonio enabled auto-merge March 31, 2025 14:38
@noonio noonio merged commit c5fddfb into master Mar 31, 2025
20 checks passed
@noonio noonio deleted the bounded-memory-loading-state branch March 31, 2025 14:44
@github-project-automation github-project-automation bot moved this from In review 👀 to Done ✔ in ☕ Hydra Team Work Mar 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Large memory usage when loading large state file

2 participants