Add Future completion subscriptions - #469
Conversation
|
Hey Simon, thank you for providing some numbers. However, the difference seems to be suspiciously high given the intended change. There's no change to fiber interactions with this PR, all it's saving is two FiberState allocations per adapter, no? Are you running with AMP_DEBUG and assertions enabled? |
|
You鈥檙e right. The previous benchmark conflated this change with an earlier GraphQL PHP optimization that removed Fiber-per-continuation handling. I misformulated what I did in AMP as I'm working on kinda larger fibers related change across multiple libs. I replaced it with an isolated comparison of GraphQL PHP鈥檚 current map()->catch()->ignore() observation against direct subscription. This Amp PR does not change Fiber behavior. The new benchmark uses 500 parent objects with six Future-backed fields per parent. Both warmed profiles execute the same query and 9 SQL requests. Assertions were enabled and AMP_DEBUG was disabled. Mind that the benchmark is not of AMP but rather what it could do in consumer code - why I'd like to make the change and expose new public API. Chained observation: 2.44 s CPU, 180 MB peak memory The saving is two derived FutureState and Future pairs per observation, plus the additional chained callback. The performance effect is realized in the GraphQL PHP adapter; this PR exposes the underlying subscription mechanism as a supported public API. I also clarified that subscription callbacks are always queued on the event loop and added tests for callback exceptions and unsubscribe-after-completion behavior. MR desc updated. |
|
Could you make the Blackfire results public? I don't have access right now. |
Context
Promise adapters may need to observe a Future completion without transforming it into another Future.
Decision
Add
Future::subscribe()andFuture::unsubscribe()as public facades for the existing one-shot completion callback mechanism.Consequences
Adapters can observe values and errors without allocating derived Future chains. Callback subscriptions can be removed before a Future completes.
Implementation Example
GraphQL PHP PR #8 uses
Future::subscribe()to replace completion observation throughmap()->catch()->ignore().The chained approach creates two derived
FutureStateandFuturepairs per observation. Direct subscription registers one callback on the original Future.Benchmark
The GraphQL PHP implementation was profiled with 500 parent objects and six Future-backed fields per parent. Both warmed profiles executed the same query and 9 SQL requests. Assertions were enabled and
AMP_DEBUGwas disabled.map()->catch()->ignore()Direct subscription reduced CPU time by approximately 26% and peak memory by approximately 19% in this profile.
View the Blackfire comparison.
The direct variant used the same underlying completion subscription mechanism exposed by this PR. These measurements demonstrate the effect in the GraphQL PHP adapter and are not a general performance guarantee.