Skip to content

Reduce per-component request-pipeline overhead#5777

Merged
BalusC merged 5 commits into
4.1from
restore_view_performance
Jun 7, 2026
Merged

Reduce per-component request-pipeline overhead#5777
BalusC merged 5 commits into
4.1from
restore_view_performance

Conversation

@BalusC

@BalusC BalusC commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Four optimizations on the per-component hot paths that run once (or more) per component per request, especially view build time and component tree walking.

  • UIComponentBase.setParent — field-back the .ADDED re-entrancy guard. It was written/read/removed as a private attribute on every setParent, routing through the reflective AttributesMap (property-descriptor miss → StateHelper lookup) each time; a plain boolean field avoids that entirely. Always cleared before returning, so it's never carried in saved state.
  • UIComponentBase.publishAfterViewEvents — iterate the live children list with a slot re-check instead of allocating an ArrayList defensive copy per node. Still safe against listeners that relocate children mid-walk (e.g. composite cc:insertChildren). Facets keep the small copy.
  • Util.componentIsDisabled / componentIsDisabledOrReadonly — read the disabled/readonly attribute directly with Boolean.TRUE.equals(...) instead of String.valueOf(...) + parseBoolean(...). These are declared boolean properties, so the stored value is always a Boolean.
  • Cache.get — probe with a plain get() before computeIfAbsent(). Steady state is a hit, and ConcurrentHashMap.get() is cheaper than computeIfAbsent(), which does extra work even on a present key. Falls back to computeIfAbsent() on a miss, preserving atomic population.

Adds UIComponentBaseTestCase coverage for the setParent re-entrancy guard.

Part of #5753.

BalusC and others added 5 commits June 5, 2026 11:57
ConcurrentHashMap.computeIfAbsent() does more work than get() even on a hit, which is the steady state for these per-class/per-component caches (renderer event info, property descriptors). Probe with a plain get() first and fall back to computeIfAbsent() only on a miss; the populate race stays atomic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
disabled/readonly are declared boolean properties on the components these helpers run against, so the attribute value is always a Boolean. Read it directly (mirroring UIComponent.isRendered()) instead of routing through String.valueOf()+parseBoolean().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e copy

The PostAddToViewEvent walk copied each component's children into a fresh ArrayList per node to guard against a listener relocating children mid-iteration (e.g. composite cc:insertChildren). Iterate the live list by index and re-check the slot after recursing instead: if it changed, the component was relocated, so process whatever now occupies it. Detects relocation after the fact, so no defensive copy and no listener-subscription knowledge is needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
setParent guarded re-entrant event processing with a private ".ADDED" attribute, whose get/put/remove on every (re)parent routed through the reflective AttributesMap (getPropertyDescriptor miss then StateHelper lookup) -- the single hottest AttributesMap.get caller. Replace it with a plain boolean field read directly in setParent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BalusC BalusC mentioned this pull request Jun 7, 2026
@BalusC BalusC merged commit f14b0ab into 4.1 Jun 7, 2026
3 checks passed
@BalusC BalusC deleted the restore_view_performance branch June 7, 2026 18:27
BalusC added a commit that referenced this pull request Jun 8, 2026
BalusC added a commit that referenced this pull request Jun 8, 2026
BalusC added a commit that referenced this pull request Jun 8, 2026
pzygielo pushed a commit to pzygielo/mojarra that referenced this pull request Jun 8, 2026
Omits eclipse-ee4j#5777's Cache get()-probe commit: 4.0's Cache.get() already probes
with get() before putIfAbsent (it never switched to computeIfAbsent), so
that change is a no-op on 4.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant