Commit d80f18a
authored
perf: Reduce GC allocations in DOM diffing (#58)
* perf: Defer OTel CDN loading to after first paint
This optimization improves First Paint performance by:
1. Installing the lightweight OTel shim synchronously (no network dependency)
2. Deferring CDN-based OTel SDK loading to requestIdleCallback/setTimeout
3. Never blocking the critical path (dotnet.create() -> runMain())
The shim provides full tracing functionality during startup, and the
CDN upgrade happens transparently in the background after first paint.
Key changes:
- Extract initLocalOtelShim() as a named synchronous function
- Extract upgradeToFullOtel() as the async CDN loading function
- Add scheduleDeferredOtelUpgrade() to run after app initialization
- Remove the blocking async IIFE that ran at module load
Performance impact:
- Before: ~4800ms First Paint (OTel CDN loading blocked startup)
- After: ~100ms First Paint (OTel loads in background)
Fixes #3 in Performance Optimization Plan
* fix: Unwrap memo nodes in MoveChild patch generation
When generating MoveChild patches for keyed diffing, the code was comparing
node types without first unwrapping memo nodes. This caused incorrect type
comparisons when memoized elements were involved in reordering operations.
Added UnwrapMemoNode() calls before type checking to ensure we compare the
actual underlying Element types, not the memo wrapper types.
* ci: Increase benchmark threshold to 15% for CI variance
CI runner benchmarks show up to 20% variance in confidence intervals due to:
- GC timing differences between runs
- Shared infrastructure resource contention
- Complex benchmarks (larger allocations) showing more variance than simple ones
Increased threshold from 110% to 115% to reduce false positives while still
catching genuine regressions. Local benchmarks confirmed variance patterns:
- CreateButtonWithHandler: ±20.30% CI
- CreateInputWithMultipleHandlers: ±19.42% CI
* perf: Defer OTel CDN loading to after first paint
Moved OpenTelemetry SDK loading from blocking script execution to
requestIdleCallback (with setTimeout fallback). This ensures:
- First paint is not blocked by CDN latency
- OTel loads during browser idle time after initial render
- Graceful degradation if CDN is slow or unavailable
The shim ensures all tracing calls work immediately, with real
implementation hydrated asynchronously after first paint.
* fix: Address OTel review comments for PR #57
Review fixes from copilot-pull-request-reviewer:
1. Early return if isOtelDisabled in initLocalOtelShim() to respect
global disable switches and avoid unnecessary shim overhead
2. Expanded fetch ignore condition to cover:
- OTLP proxy endpoint (/otlp/v1/traces)
- Common collector endpoints (/v1/traces)
- Custom configured exporter URL
- Blazor framework downloads (/_framework/)
3. Restore original fetch before registering full OTel instrumentations
to prevent double-patching and context propagation issues
4. Fix setVerbosity cache invalidation - both shim and full OTel now
call resetVerbosityCache() so runtime verbosity changes take effect
5. Fix header guard that always evaluated to true (i && i.headers)
* Cache Playwright browsers in CI workflow
Add caching for Playwright browsers to improve CI performance.
* perf: Reduce GC allocations in DOM diffing
- Pool PatchData lists using ConcurrentQueue to avoid allocations in ApplyBatch
- Replace ComputeLIS array allocations with ArrayPool<int>.Shared rentals
- Replace HashSet<int> for LIS membership with ArrayPool<bool>.Shared rental
Benchmark impact (js-framework-benchmark):
- Clear (09_clear1k): 173.2ms → 159.6ms (8% improvement)
- Clear GC time: 18.1% → 12.2% (33% reduction)
- Swap GC time: 10.4% → 9.4% (10% reduction)
Also documents the dotnet format multi-targeting issue in memory.instructions.md1 parent 671652a commit d80f18a
File tree
2 files changed
+173
-67
lines changed- .github/instructions
- Abies/DOM
2 files changed
+173
-67
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
83 | 97 | | |
84 | 98 | | |
85 | 99 | | |
| |||
170 | 184 | | |
171 | 185 | | |
172 | 186 | | |
173 | | - | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
174 | 245 | | |
175 | | - | |
176 | | - | |
177 | | - | |
| 246 | + | |
178 | 247 | | |
179 | | - | |
180 | 248 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
754 | 754 | | |
755 | 755 | | |
756 | 756 | | |
| 757 | + | |
757 | 758 | | |
758 | 759 | | |
759 | 760 | | |
| |||
845 | 846 | | |
846 | 847 | | |
847 | 848 | | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
848 | 867 | | |
849 | 868 | | |
850 | 869 | | |
| |||
979 | 998 | | |
980 | 999 | | |
981 | 1000 | | |
982 | | - | |
983 | | - | |
984 | | - | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
985 | 1004 | | |
986 | | - | |
987 | | - | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
988 | 1010 | | |
989 | | - | |
990 | | - | |
991 | | - | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
992 | 1019 | | |
993 | 1020 | | |
994 | 1021 | | |
| |||
1551 | 1578 | | |
1552 | 1579 | | |
1553 | 1580 | | |
| 1581 | + | |
| 1582 | + | |
1554 | 1583 | | |
1555 | 1584 | | |
1556 | 1585 | | |
| |||
1559 | 1588 | | |
1560 | 1589 | | |
1561 | 1590 | | |
1562 | | - | |
1563 | | - | |
1564 | | - | |
1565 | | - | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + | |
1566 | 1594 | | |
1567 | 1595 | | |
1568 | 1596 | | |
| |||
1576 | 1604 | | |
1577 | 1605 | | |
1578 | 1606 | | |
1579 | | - | |
| 1607 | + | |
1580 | 1608 | | |
1581 | 1609 | | |
1582 | 1610 | | |
| |||
1605 | 1633 | | |
1606 | 1634 | | |
1607 | 1635 | | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
1608 | 1639 | | |
1609 | 1640 | | |
1610 | 1641 | | |
| |||
1767 | 1798 | | |
1768 | 1799 | | |
1769 | 1800 | | |
1770 | | - | |
1771 | | - | |
| 1801 | + | |
| 1802 | + | |
1772 | 1803 | | |
1773 | | - | |
| 1804 | + | |
1774 | 1805 | | |
1775 | 1806 | | |
| 1807 | + | |
| 1808 | + | |
1776 | 1809 | | |
1777 | 1810 | | |
1778 | | - | |
1779 | | - | |
| 1811 | + | |
| 1812 | + | |
1780 | 1813 | | |
1781 | 1814 | | |
1782 | 1815 | | |
1783 | 1816 | | |
1784 | | - | |
| 1817 | + | |
1785 | 1818 | | |
1786 | 1819 | | |
1787 | | - | |
1788 | | - | |
1789 | | - | |
1790 | | - | |
1791 | | - | |
| 1820 | + | |
| 1821 | + | |
| 1822 | + | |
1792 | 1823 | | |
1793 | | - | |
| 1824 | + | |
1794 | 1825 | | |
1795 | | - | |
| 1826 | + | |
1796 | 1827 | | |
1797 | | - | |
1798 | | - | |
1799 | | - | |
1800 | | - | |
1801 | | - | |
1802 | | - | |
1803 | | - | |
1804 | | - | |
| 1828 | + | |
1805 | 1829 | | |
1806 | | - | |
1807 | | - | |
1808 | | - | |
| 1830 | + | |
| 1831 | + | |
| 1832 | + | |
| 1833 | + | |
1809 | 1834 | | |
1810 | | - | |
1811 | | - | |
| 1835 | + | |
| 1836 | + | |
| 1837 | + | |
| 1838 | + | |
| 1839 | + | |
| 1840 | + | |
| 1841 | + | |
| 1842 | + | |
| 1843 | + | |
| 1844 | + | |
| 1845 | + | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
| 1857 | + | |
1812 | 1858 | | |
1813 | | - | |
| 1859 | + | |
1814 | 1860 | | |
1815 | | - | |
| 1861 | + | |
| 1862 | + | |
1816 | 1863 | | |
1817 | | - | |
| 1864 | + | |
1818 | 1865 | | |
1819 | 1866 | | |
| 1867 | + | |
1820 | 1868 | | |
1821 | | - | |
1822 | | - | |
1823 | | - | |
1824 | | - | |
1825 | | - | |
1826 | | - | |
1827 | | - | |
1828 | | - | |
1829 | | - | |
1830 | | - | |
| 1869 | + | |
| 1870 | + | |
| 1871 | + | |
| 1872 | + | |
| 1873 | + | |
| 1874 | + | |
| 1875 | + | |
1831 | 1876 | | |
1832 | 1877 | | |
1833 | | - | |
1834 | | - | |
1835 | | - | |
1836 | | - | |
1837 | | - | |
1838 | | - | |
| 1878 | + | |
1839 | 1879 | | |
1840 | | - | |
1841 | | - | |
| 1880 | + | |
| 1881 | + | |
1842 | 1882 | | |
1843 | | - | |
1844 | | - | |
1845 | 1883 | | |
1846 | 1884 | | |
1847 | 1885 | | |
| |||
0 commit comments