From ce0a56bcda713fd1ec996acf5bfd1aadb2431195 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Fri, 21 Mar 2025 09:11:46 +0000 Subject: [PATCH] perf(@angular/ssr): optimized request handling performance This commit refactors request handling logic, leading to significant performance improvements. **Benchmark** | Metric | 19.2.x Branch | Main Branch | After Optimization | Improvement vs 19.2.x | Improvement vs Main | |--------------------|-----------------------|----------------------|---------------------|-----------------------|-----------------------| | Latency (Avg) | 2473.94 ms | 2655.35 ms | 2385.85 ms | ~3.6% | ~10.1% | | Latency (50%) | 2445.67 ms | 2615 ms | 2416.33 ms | ~1.2% | ~7.6% | | Latency (97.5%) | 2640.5 ms | 3309 ms | 2561.5 ms | ~3.0% | ~22.6% | | Req/Sec (Avg) | 398.32 | 364.54 | 400.12 | ~0.4% | ~9.8% | | Bytes/Sec (Avg) | 8.41 MB | 7.7 MB | 8.45 MB | ~0.5% | ~9.7% | | Total Requests | 13,000 | 12,000 | 13,000 | 0% | ~8.3% | **Test Details:** * **Command:** `npx autocannon -c 100 -d 30 -p 10 http://localhost:` * **Parameters:** * `-c 100`: 100 concurrent connections * `-d 30`: 30 seconds duration * `-p 10`: 10 pipelining factor * **Iterations:** 3 tests were run on each of the Main Branch and the 19.2.x Branch, and 3 tests were run after optimization. Average of each set of tests was used for the comparison. * **Samples:** 30 samples were collected per test run for Req/Bytes counts. The optimized request handling logic (After Optimization) shows significant improvements across all key performance metrics compared to the original logic on the Main Branch. The regression observed in the Main Branch is attributed to the newly added header flushing logic. When compared to the 19.2.x branch, the optimized code delivers similar performance. Latency is slightly reduced, while request throughput (Req/Sec) and data transfer rate (Bytes/Sec) have seen a slight increase. The total number of requests handled remains consistent with the 19.2.x branch. --- packages/angular/ssr/src/utils/ng.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/angular/ssr/src/utils/ng.ts b/packages/angular/ssr/src/utils/ng.ts index d43ffdefc1dc..98c0e7be99d2 100644 --- a/packages/angular/ssr/src/utils/ng.ts +++ b/packages/angular/ssr/src/utils/ng.ts @@ -95,13 +95,16 @@ export async function renderAngular( await applicationRef.whenStable(); return { - content: async () => { - try { - return renderInternal(platformRef, applicationRef); - } finally { - await asyncDestroyPlatform(platformRef); - } - }, + content: () => + new Promise((resolve, reject) => { + // Defer rendering to the next event loop iteration to avoid blocking, as most operations in `renderInternal` are synchronous. + setTimeout(() => { + renderInternal(platformRef, applicationRef) + .then(resolve) + .catch(reject) + .finally(() => void asyncDestroyPlatform(platformRef)); + }, 0); + }), }; } catch (error) { await asyncDestroyPlatform(platformRef);