You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2026/10/16 15:53:02 UTC

(cxf) branch main updated: CXF-7641: Reduce allocations in CachingXmlEventWriter (#3592)

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new 5354732d878 CXF-7641: Reduce allocations in CachingXmlEventWriter (#3592)
5354732d878 is described below

commit 5354732d878ecae81391e049701e518084b0873d
Author: Colm O hEigeartaigh <co...@users.noreply.github.com>
AuthorDate: Fri Oct 16 16:52:55 2026 +0100

    CXF-7641: Reduce allocations in CachingXmlEventWriter (#3592)
---
 .../cxf/staxutils/CachingXmlEventWriter.java       | 25 ++++++++++++++++------
 .../org/apache/cxf/staxutils/StaxUtilsTest.java    | 23 ++++++++++++++++++++
 2 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java b/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java
index 9900ee0308f..de4d7b02672 100644
--- a/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java
+++ b/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java
@@ -157,12 +157,12 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
     }
 
     public void setDefaultNamespace(String ns) throws XMLStreamException {
-        curContext.addNs("", ns);
+        addNs("", ns);
     }
 
 
     public void writeNamespace(String pfx, String ns) throws XMLStreamException {
-        curContext.addNs(pfx, ns);
+        addNs(pfx, ns);
         if (StringUtils.isEmpty(pfx)) {
             addEvent(factory.createNamespace(ns));
         } else {
@@ -179,7 +179,18 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
         }
     }
     public void setPrefix(String pfx, String uri) throws XMLStreamException {
-        curContext.addNs(pfx, uri);
+        addNs(pfx, uri);
+    }
+
+    /**
+     * Elements share their parent's namespace context until they declare a namespace,
+     * to avoid allocating a context per element when buffering large documents.
+     */
+    private void addNs(String pfx, String ns) {
+        if (!contexts.isEmpty() && curContext == contexts.peek()) {
+            curContext = new NSContext(curContext);
+        }
+        curContext.addNs(pfx, ns);
     }
 
 
@@ -211,7 +222,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
     public void writeStartElement(String name) throws XMLStreamException {
         elNames.push(lastStart);
         contexts.push(curContext);
-        curContext = new NSContext(curContext);
         lastStart = new QName(name);
         Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet();
         Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet();
@@ -220,7 +230,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
     public void writeStartElement(String name, String ns) throws XMLStreamException {
         elNames.push(lastStart);
         contexts.push(curContext);
-        curContext = new NSContext(curContext);
         lastStart = new QName(ns, name);
         Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet();
         Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet();
@@ -229,7 +238,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
     public void writeStartElement(String pfx, String name, String ns) throws XMLStreamException {
         elNames.push(lastStart);
         contexts.push(curContext);
-        curContext = new NSContext(curContext);
         lastStart = new QName(ns, name, pfx);
         Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet();
         Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet();
@@ -238,12 +246,15 @@ public class CachingXmlEventWriter implements XMLStreamWriter {
 
     public static class NSContext implements NamespaceContext {
         NamespaceContext parent;
-        Map<String, String> map = new HashMap<>();
+        Map<String, String> map = Collections.emptyMap();
 
         public NSContext(NamespaceContext p) {
             parent = p;
         }
         public void addNs(String pfx, String ns) {
+            if (map.isEmpty()) {
+                map = new HashMap<>();
+            }
             map.put(pfx, ns);
         }
 
diff --git a/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java b/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java
index 54b1c0ba657..ac0a54c98af 100644
--- a/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java
+++ b/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java
@@ -61,6 +61,7 @@ import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -443,6 +444,28 @@ public class StaxUtilsTest {
         assertEquals(-1, idx);
     }
 
+    @Test
+    public void testCachingXmlEventWriterNamespaceScope() throws Exception {
+        CachingXmlEventWriter writer = new CachingXmlEventWriter();
+        writer.writeStartElement("root");
+        writer.writeStartElement("a", "first", "urn:a");
+        writer.writeNamespace("a", "urn:a");
+        writer.writeStartElement("child");
+        assertEquals("urn:a", writer.getNamespaceContext().getNamespaceURI("a"));
+        assertEquals("a", writer.getPrefix("urn:a"));
+        writer.writeEndElement();
+        writer.writeEndElement();
+        assertNull(writer.getNamespaceContext().getNamespaceURI("a"));
+        writer.writeStartElement("second");
+        assertNull(writer.getNamespaceContext().getNamespaceURI("a"));
+        assertNull(writer.getPrefix("urn:a"));
+        writer.setPrefix("b", "urn:b");
+        assertEquals("urn:b", writer.getNamespaceContext().getNamespaceURI("b"));
+        writer.writeEndElement();
+        assertNull(writer.getNamespaceContext().getNamespaceURI("b"));
+        writer.writeEndElement();
+    }
+
     @Test
     public void testCopyWithEmptyNamespace() throws Exception {
         StringBuilder in = new StringBuilder(128);