Commit 5234506
authored
fix(fiber): bound runner memory under sustained Fibre load (#3306)
* fix(solo,reaping): bound sequencer queue to prevent ingest-side OOM
Under sustained ingest above the block-production drain rate,
SoloSequencer.queue grew monotonically. A 32-vCPU loadgen pushing
>100 MB/s into a runner whose executor drains ~100 MB/s per block
filled the queue at ~150 MB/s of net-positive growth — heap
profiles showed 24 GB of retained io.ReadAll bytes in the queue
within ~30 s, then anon-rss:63GB OOM-kill at the box's 64 GiB
ceiling. Reproducible twice with identical signature.
Two changes, one feature:
- SoloSequencer.SetMaxQueueBytes(n) caps the queue's total
retained tx bytes. SubmitBatchTxs uses all-or-nothing admission
against the cap: if the incoming batch would push us over, the
whole batch is rejected with ErrQueueFull and the queue keeps
its current contents untouched. Partial admission would force
the caller to track which prefix succeeded and only re-feed the
suffix on retry; the reaper currently doesn't do that, so the
whole-batch rule lets the reaper just retry the same batch
later when the queue has drained. queueBytes is decremented
on drain (queue := nil) and re-counted for postponed txs that
the executor's FilterTxs returns to the queue. Zero cap = the
legacy unbounded path, preserved for tests and small
deployments.
- The reaper bridging executor mempool → sequencer matches
ErrQueueFull via errors.Is and treats it as transient
backpressure: marks the rejected hashes as "seen" so the
next reaper tick doesn't re-hash + re-submit the same already-
rejected txs forever, logs a warn line with the dropped count,
and continues running. Without this match every queue-full
event would tear the daemon down via the existing fatal-on-
submit-error path.
Loadgen sees the backpressure indirectly: with the sequencer
queue full, the executor's txChan stops draining, /tx blocks on
its bounded channel send, and txsim observes 5xx / timeouts —
cleanly applied at the application layer instead of via the
kernel OOM-killer.
* fix(evnode-fibre): enforce maxBytes in inMemExecutor.FilterTxs
The stub executor used by the runner returned FilterOK for
every transaction unconditionally, ignoring the maxBytes
budget plumbed through SoloSequencer.GetNextBatch. Under
sustained txsim load (~50 MiB/s, 8 concurrent senders) the
mempool would accumulate ~50K txs while a 100 MiB upload
was in flight; on the next batch the sequencer drained
ALL of them into one block (~369 MiB raw), the submitter
saw a single item exceeding the per-blob cap, and halted
the node with `single item exceeds DA blob size limit`.
Walk the input txs in arrival order, accumulate sizes
against maxBytes, and return FilterPostpone past the
budget so the sequencer puts the overflow back on its
queue. Verified live: blocks now cap at ~10K txs / ~100
MiB and evnode sustains 58.77 MB/s DA upload throughput
through a 5-min txsim run with zero crashes (was 0 →
crash within 30 s before this fix).
* fix(evnode-fibre): wire sequencer queue cap + lift ingest queue caps
Two runner-side changes paired with the SoloSequencer bound:
- After constructing the SoloSequencer, call SetMaxQueueBytes
with 10× the per-block tx budget (= 1 GiB at the current 100
MiB MaxBlobSize). 10× is the sweet spot: large enough that a
short burst above steady-state ingest doesn't trigger
backpressure (we want to absorb that), small enough that the
worst-case retained bytes fit comfortably under the box's
RAM budget alongside the pending cache + DA in-flight buffers.
- Lift the inMemExecutor's hardcoded ingest caps. txChan and
maxBlockTxs were sized at 500 (5 MB / 5K txs per reaper poll)
back when those were the only memory bound on the runner. With
the SetMaxQueueBytes cap and the FilterTxs-enforced per-block
budget now actually doing the bounding, the ingest queue can
hold a full 100 MiB block-worth of txs (10K slots at 10 KB)
without burdening memory — and a single reaper poll can
drain that whole batch in one GetTxs call instead of
needing 20× cycles. This was the binding constraint at
~5,000 tx/s = 50 MB/s in earlier runs.
* fix(config): tighten Fiber pending cap to 10 to bound submitter memory
ApplyFiberDefaults set MaxPendingHeadersAndData=50, but each pending
data item under Fiber is up to MaxBlobSize (~100 MiB raw). With
3-FSP fan-out and per-attempt retry buffers in flight, 50 items × 3
× retries crossed 64 GiB on c6in.8xlarge under sustained txsim load
and the kernel OOM-killed evnode 30 s into the run.
10 keeps the in-flight footprint bounded while still letting healthy
uploads pipeline against the actual Fibre RPC latency. Verified by
heap profiling: pending pause at ~ 10 × 100 MiB plus fan-out keeps
RSS below ~10 GiB, evnode runs indefinitely.1 parent 513ce9b commit 5234506
4 files changed
Lines changed: 125 additions & 20 deletions
File tree
- block/internal/reaping
- pkg
- config
- sequencers/solo
- tools/celestia-node-fiber/cmd/evnode-fibre
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
193 | 194 | | |
194 | 195 | | |
195 | 196 | | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
196 | 208 | | |
197 | 209 | | |
198 | 210 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
367 | 367 | | |
368 | 368 | | |
369 | 369 | | |
370 | | - | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
371 | 376 | | |
372 | 377 | | |
373 | 378 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
18 | 26 | | |
19 | 27 | | |
20 | 28 | | |
| |||
27 | 35 | | |
28 | 36 | | |
29 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
30 | 47 | | |
31 | 48 | | |
32 | 49 | | |
33 | 50 | | |
34 | 51 | | |
35 | 52 | | |
36 | 53 | | |
37 | | - | |
38 | | - | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
39 | 58 | | |
40 | 59 | | |
41 | 60 | | |
| |||
51 | 70 | | |
52 | 71 | | |
53 | 72 | | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
54 | 83 | | |
55 | 84 | | |
56 | 85 | | |
| |||
67 | 96 | | |
68 | 97 | | |
69 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
70 | 121 | | |
| 122 | + | |
71 | 123 | | |
72 | 124 | | |
73 | 125 | | |
| |||
79 | 131 | | |
80 | 132 | | |
81 | 133 | | |
| 134 | + | |
82 | 135 | | |
83 | 136 | | |
84 | 137 | | |
| |||
122 | 175 | | |
123 | 176 | | |
124 | 177 | | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
125 | 186 | | |
126 | 187 | | |
127 | 188 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
327 | 327 | | |
328 | 328 | | |
329 | 329 | | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
330 | 343 | | |
331 | 344 | | |
332 | 345 | | |
| |||
479 | 492 | | |
480 | 493 | | |
481 | 494 | | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
490 | 504 | | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
495 | 508 | | |
496 | 509 | | |
497 | | - | |
498 | | - | |
| 510 | + | |
| 511 | + | |
499 | 512 | | |
500 | 513 | | |
501 | 514 | | |
| |||
547 | 560 | | |
548 | 561 | | |
549 | 562 | | |
550 | | - | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
551 | 571 | | |
552 | | - | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
553 | 579 | | |
| 580 | + | |
554 | 581 | | |
555 | 582 | | |
556 | 583 | | |
| |||
0 commit comments