You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2026/07/07 21:11:50 UTC
(myfaces) branch main updated: [perf] improve initial collection size
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/main by this push:
new 6f38195d9 [perf] improve initial collection size
6f38195d9 is described below
commit 6f38195d980c12051f6e4d5318bc423b3640f58e
Author: tandraschko <ta...@apache.org>
AuthorDate: Tue Jul 7 23:11:38 2026 +0200
[perf] improve initial collection size
---
.../myfaces/application/ApplicationImpl.java | 25 +++++++++++++++-------
.../application/FacesServletMappingUtils.java | 14 ++++++------
.../myfaces/application/NavigationHandlerImpl.java | 11 ++++++----
.../myfaces/application/TreeStructureManager.java | 7 +++---
.../context/servlet/RequestHeaderValuesMap.java | 6 +++++-
.../servlet/ServletExternalContextImpl.java | 15 +++++++++----
.../apache/myfaces/lifecycle/LifecycleImpl.java | 6 +++++-
7 files changed, 56 insertions(+), 28 deletions(-)
diff --git a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
index 0eac5d3f8..2e93e523d 100755
--- a/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/application/ApplicationImpl.java
@@ -167,6 +167,8 @@ public class ApplicationImpl extends Application
private StateManager _stateManager;
private FlowHandler _flowHandler;
+ private static final ELContextListener[] EMPTY_EL_CONTEXT_LISTENERS = new ELContextListener[0];
+
private ArrayList<ELContextListener> _elContextListeners;
// components, converters, and validators can be added at runtime--must
@@ -552,7 +554,9 @@ public final ELContextListener[] getELContextListeners()
// this gets called on every request, so I can't afford to synchronize
// I just have to trust that toArray() with do the right thing if the
// list is changing (not likely)
- return _elContextListeners.toArray(new ELContextListener[_elContextListeners.size()]);
+ return _elContextListeners.isEmpty()
+ ? EMPTY_EL_CONTEXT_LISTENERS
+ : _elContextListeners.toArray(new ELContextListener[_elContextListeners.size()]);
}
@Override
@@ -1680,15 +1684,17 @@ private void _handleAttachedResourceDependencyAnnotations(FacesContext context,
List<ResourceDependency> dependencyList = _classToResourceDependencyMap.get(inspectedClass);
if (dependencyList == null)
{
- dependencyList = new ArrayList<>(5);
-
ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
+ ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
+
+ dependencyList = new ArrayList<>((dependency != null ? 1 : 0)
+ + (dependencies != null ? dependencies.value().length : 0));
+
if (dependency != null)
{
dependencyList.add(dependency);
}
- ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
if (dependencies != null)
{
dependencyList.addAll(Arrays.asList(dependencies.value()));
@@ -2012,15 +2018,17 @@ private void _handleListenerForAnnotations(FacesContext context, Object inspecte
List<ListenerFor> listenerForList = _classToListenerForMap.get(inspectedClass);
if (listenerForList == null)
{
- listenerForList = new ArrayList<>(5);
-
ListenerFor listener = inspectedClass.getAnnotation(ListenerFor.class);
+ ListenersFor listeners = inspectedClass.getAnnotation(ListenersFor.class);
+
+ listenerForList = new ArrayList<>((listener != null ? 1 : 0)
+ + (listeners != null ? listeners.value().length : 0));
+
if (listener != null)
{
listenerForList.add(listener);
}
- ListenersFor listeners = inspectedClass.getAnnotation(ListenersFor.class);
if (listeners != null)
{
listenerForList.addAll(Arrays.asList(listeners.value()));
@@ -2147,7 +2155,8 @@ private void _handleResourceDependencyAnnotations(FacesContext context, Class<?>
if(dependency != null || dependencies != null)
{
//resource dependencies were found using one or both annotations, create and build a new list
- dependencyList = new ArrayList<>();
+ dependencyList = new ArrayList<>((dependency != null ? 1 : 0)
+ + (dependencies != null ? dependencies.value().length : 0));
if(dependency != null)
{
diff --git a/impl/src/main/java/org/apache/myfaces/application/FacesServletMappingUtils.java b/impl/src/main/java/org/apache/myfaces/application/FacesServletMappingUtils.java
index e39666398..7353fdd54 100644
--- a/impl/src/main/java/org/apache/myfaces/application/FacesServletMappingUtils.java
+++ b/impl/src/main/java/org/apache/myfaces/application/FacesServletMappingUtils.java
@@ -40,6 +40,8 @@ public class FacesServletMappingUtils
private static final String SERVLET_REGISTRATIONS = "org.apache.myfaces.SERVLET_REGISTRATIONS";
private static final String CURRENT_REQUEST_FACES_SERVLET = "org.apache.myfaces.CURRENT_FACES_SERVLET_MAPPING";
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* Wrapper for better performance
@@ -58,11 +60,9 @@ public ServletRegistrationInfo(ServletRegistration registration, boolean facesSe
this.registration = registration;
Collection<String> mappingsCollection = registration.getMappings();
- mappings = mappingsCollection.toArray(new String[mappingsCollection.size()]);
- if (mappings == null)
- {
- mappings = new String[]{ };
- }
+ mappings = mappingsCollection.isEmpty()
+ ? EMPTY_STRING_ARRAY
+ : mappingsCollection.toArray(new String[mappingsCollection.size()]);
}
public String getClassName()
@@ -115,9 +115,9 @@ public static List<ServletRegistrationInfo> getServletRegistrations(FacesContext
(List<ServletRegistrationInfo>) applicationMap.get(SERVLET_REGISTRATIONS);
if (infos == null)
{
- infos = new ArrayList<>();
-
Map<String, ? extends ServletRegistration> registrations = servletContext.getServletRegistrations();
+ infos = new ArrayList<>(registrations != null ? registrations.size() : 0);
+
if (registrations != null)
{
for (ServletRegistration servletRegistration : registrations.values())
diff --git a/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java b/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
index 7b86dfcac..426159e6e 100755
--- a/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
@@ -186,7 +186,7 @@ else if (fromViewId != null && !fromViewId.equals(toViewId))
// MYFACES-4504: check isEmpty()
if (navigationCaseParameters == null || navigationCaseParameters.isEmpty())
{
- navigationCaseParameters = new HashMap<>(5, 1f);
+ navigationCaseParameters = new HashMap<>(3, 1f);
}
// If current flow (sourceFlow) is not null and new flow (targetFlow) is null,
@@ -1156,7 +1156,8 @@ private NavigationCase getOutcomeNavigationCase(FacesContext facesContext, Strin
List<String> paramValues = params.get(splitParam[0]);
if (paramValues == null)
{
- paramValues = new ArrayList<>(5);
+ // most parameters only occur once; grows automatically for repeated names
+ paramValues = new ArrayList<>(1);
params.put(splitParam[0], paramValues);
}
paramValues.add(splitParam[1]);
@@ -1406,7 +1407,8 @@ public void inspectFlow(FacesContext context, Flow flow)
Map<String, Set<NavigationCase>> cases = new HashMap<>(HashMapUtils.calcCapacity(rulesSize));
- List<_WildcardPattern> wildcardPatterns = new ArrayList<>();
+ // at most one wildcard pattern is added per distinct fromViewId, bounded by rulesSize
+ List<_WildcardPattern> wildcardPatterns = new ArrayList<>(rulesSize);
for (Map.Entry<String, Set<NavigationCase>> entry : rules.entrySet())
{
@@ -1454,7 +1456,8 @@ private synchronized void calculateNavigationCases(RuntimeConfig runtimeConfig)
Map<String, Set<NavigationCase>> cases = new HashMap<>(HashMapUtils.calcCapacity(rulesSize));
- List<_WildcardPattern> wildcardPatterns = new ArrayList<>();
+ // at most one wildcard pattern is added per distinct fromViewId, bounded by rulesSize
+ List<_WildcardPattern> wildcardPatterns = new ArrayList<>(rulesSize);
for (NavigationRule rule : rules)
{
String fromViewId = rule.getFromViewId();
diff --git a/impl/src/main/java/org/apache/myfaces/application/TreeStructureManager.java b/impl/src/main/java/org/apache/myfaces/application/TreeStructureManager.java
index 052eb64d8..419c43075 100755
--- a/impl/src/main/java/org/apache/myfaces/application/TreeStructureManager.java
+++ b/impl/src/main/java/org/apache/myfaces/application/TreeStructureManager.java
@@ -54,7 +54,7 @@ private static TreeStructComponent internalBuildTreeStructureToSave(UIComponent
if (childCount > 0)
{
List<UIComponent> children = component.getChildren();
- List<TreeStructComponent> structChildList = new ArrayList<>();
+ List<TreeStructComponent> structChildList = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++)
{
UIComponent child = children.get(i);
@@ -71,10 +71,11 @@ private static TreeStructComponent internalBuildTreeStructureToSave(UIComponent
}
//facets
- if (component.getFacetCount() > 0)
+ int facetCount = component.getFacetCount();
+ if (facetCount > 0)
{
Map<String, UIComponent> facetMap = component.getFacets();
- List<Object[]> structFacetList = new ArrayList<>();
+ List<Object[]> structFacetList = new ArrayList<>(facetCount);
for (Map.Entry<String, UIComponent> entry : facetMap.entrySet())
{
UIComponent child = entry.getValue();
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
index dbcf6c7fb..0c936ad94 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/RequestHeaderValuesMap.java
@@ -36,6 +36,8 @@
*/
public final class RequestHeaderValuesMap extends AbstractAttributeMap<String[]>
{
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
private final HttpServletRequest httpServletRequest;
private final Map<String, String[]> attributeValueCache = new HashMap<>();
@@ -52,7 +54,9 @@ protected String[] getAttribute(final String key)
{
List<String> attributesList = Collections.list(httpServletRequest.getHeaders(key));
- attributes = attributesList.toArray(new String[attributesList.size()]);
+ attributes = attributesList.isEmpty()
+ ? EMPTY_STRING_ARRAY
+ : attributesList.toArray(new String[attributesList.size()]);
attributeValueCache.put(key, attributes);
}
diff --git a/impl/src/main/java/org/apache/myfaces/context/servlet/ServletExternalContextImpl.java b/impl/src/main/java/org/apache/myfaces/context/servlet/ServletExternalContextImpl.java
index 67075ff8a..2de1e56ad 100755
--- a/impl/src/main/java/org/apache/myfaces/context/servlet/ServletExternalContextImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/context/servlet/ServletExternalContextImpl.java
@@ -891,7 +891,9 @@ private String encodeURL(String baseUrl, Map<String, List<String>> parameters)
if (paramMap == null)
{
- paramMap = new HashMap<>(5, 1f);
+ // nameValuePairs.length is an upper bound on the number of distinct
+ // parameter names (duplicates just mean fewer), so it never resizes
+ paramMap = new HashMap<>(nameValuePairs.length, 1f);
}
List<String> values = paramMap.get(currentName);
@@ -926,7 +928,9 @@ private String encodeURL(String baseUrl, Map<String, List<String>> parameters)
{
if (paramMap == null)
{
- paramMap = new HashMap<>(5, 1f);
+ // parameters.size() is an upper bound on the number of entries
+ // that will be put into paramMap in this loop
+ paramMap = new HashMap<>(parameters.size(), 1f);
}
paramMap.put(key, pair.getValue());
}
@@ -937,9 +941,13 @@ private String encodeURL(String baseUrl, Map<String, List<String>> parameters)
ClientWindow window = facesContext.getExternalContext().getClientWindow();
if (window != null && window.isClientWindowRenderModeEnabled(facesContext))
{
+ Map<String, String> additionalQueryURLParameters = window.getQueryURLParameters(facesContext);
+
if (paramMap == null)
{
- paramMap = new HashMap<>(5, 1f);
+ // upper bound: the client window id param plus any additional query params
+ paramMap = new HashMap<>(1 + (additionalQueryURLParameters != null
+ ? additionalQueryURLParameters.size() : 0), 1f);
}
if (!paramMap.containsKey(ResponseStateManager.CLIENT_WINDOW_URL_PARAM))
@@ -947,7 +955,6 @@ private String encodeURL(String baseUrl, Map<String, List<String>> parameters)
paramMap.put(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, Arrays.asList(window.getId()));
}
- Map<String, String> additionalQueryURLParameters = window.getQueryURLParameters(facesContext);
if (additionalQueryURLParameters != null)
{
for (Map.Entry<String , String> entry : additionalQueryURLParameters.entrySet())
diff --git a/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java b/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
index c2e106197..f3b2be48d 100755
--- a/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
@@ -52,6 +52,8 @@
public class LifecycleImpl extends Lifecycle
{
private static final Logger log = Logger.getLogger(LifecycleImpl.class.getName());
+
+ private static final PhaseListener[] EMPTY_PHASE_LISTENERS = new PhaseListener[0];
/**
* Boolean.TRUE is stored under this key in the application map if
@@ -346,7 +348,9 @@ public void removePhaseListener(PhaseListener phaseListener)
@Override
public PhaseListener[] getPhaseListeners()
{
- return phaseListeners.toArray(new PhaseListener[phaseListeners.size()]);
+ return phaseListeners.isEmpty()
+ ? EMPTY_PHASE_LISTENERS
+ : phaseListeners.toArray(new PhaseListener[phaseListeners.size()]);
}
private void publishException(Throwable e, PhaseId phaseId, FacesContext facesContext)