impl(o11y): box futures in DiscoveryPoller to prevent stack overflow#5918
impl(o11y): box futures in DiscoveryPoller to prevent stack overflow#5918haphungw wants to merge 4 commits into
DiscoveryPoller to prevent stack overflow#5918Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors DiscoveryPoller to use boxed futures (BoxedFuture) instead of generic parameters S and Q, simplifying the type signatures and trait implementations. The feedback suggests shadowing the query parameter instead of naming it query_clone to avoid confusion, as the variable is moved into the closure rather than cloned.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5918 +/- ##
=======================================
Coverage 97.90% 97.90%
=======================================
Files 234 234
Lines 59451 59458 +7
=======================================
+ Hits 58204 58211 +7
Misses 1247 1247 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| } | ||
| } | ||
|
|
||
| type BoxedFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'static>>; |
There was a problem hiding this comment.
This should have a comment saying something about the tradeoffs we are making:
- Instrumented LRO futures can get very large and cause stack overflows, so we need to box them.
- The impact of moving these to the heap should be OK since polling is bound to network requests.
I'd also suggest having a Rust expert give you feedback as well, in case there are gotchas or alternatives we aren't considering.
When tracing is enabled,
DiscoveryPolleris wrapped inside nesting decorators. Because it uses generic type parametersS(start future) andQ(query future), the compiler generates extremely deeply nested type definitions for every generic type combination.At runtime, executing these deeply nested future types requires a lot of stack memory, resulting in a stack overflow in LRO-heavy tests (
compute::run_compute_lro_errors).Therefore, instead of keeping the futures as generic type parameters, we store them as boxed futures on the heap (
Pin<Box<dyn Future + Send>>). This erases their concrete types and flattens their size on the stack.