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 2 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.
| let mut query_clone = query; | ||
| let start_boxed = Box::pin(start()); | ||
| let query_boxed = Box::new(move |name| Box::pin(query_clone(name)) as BoxedFuture<Result<O>>); |
There was a problem hiding this comment.
The variable is named query_clone, but it is actually moved into the closure rather than cloned. To avoid confusion and improve readability, you can simply shadow the query parameter.
| let mut query_clone = query; | |
| let start_boxed = Box::pin(start()); | |
| let query_boxed = Box::new(move |name| Box::pin(query_clone(name)) as BoxedFuture<Result<O>>); | |
| let mut query = query; | |
| let start_boxed = Box::pin(start()); | |
| let query_boxed = Box::new(move |name| Box::pin(query(name)) as BoxedFuture<Result<O>>); |
References
- Encourage modern, efficient, and readable Rust code. (link)
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 58212 +8
+ Misses 1247 1246 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.