Skip to content

Fix O(n²) sequential element access in XmlComplexContentImpl setter helpers (XMLBEANS-438) - #2

Draft
pjfanning with Copilot wants to merge 3 commits into
trunkfrom
copilot/improve-performance-reading-xobj-data
Draft

Fix O(n²) sequential element access in XmlComplexContentImpl setter helpers (XMLBEANS-438)#2
pjfanning with Copilot wants to merge 3 commits into
trunkfrom
copilot/improve-performance-reading-xobj-data

Conversation

Copilot AI commented Apr 21, 2026

Copy link
Copy Markdown

When saving large XLSX files via POI, arraySetterHelper iterates over N source elements and for each calls find_element_user(QName, int i) with a monotonically increasing i. Since find_element_user always rescans from _firstChild, this is O(n) per call — O(n²) total for N elements.

Changes

  • commonSetterHelper / commonSetterHelper2: Pre-fetch all existing child elements once with find_all_element_users (O(n)) before the loop, then use O(1) list indexing instead of find_element_user(name, i) on each iteration.

  • arraySetterHelper fast-path inner loop: Replaces the per-iteration find_element_user(name, j) call with existingList.get(j - originalI - insertCount). An insertCount counter tracks in-loop insertions that shift the original elements rightward in the store, keeping the index arithmetic correct without re-scanning.

  • arraySetterHelper general-case final loop: Lazily builds a finalList after the excess-removal pass, then uses finalList.get(j) for existing positions instead of find_element_user(name, j).

Before:

// O(n) scan from _firstChild on every call — O(n²) total
for (int i = 0; i < n; i++) {
    user = store.find_element_user(elemName, i); // rescans from _firstChild each time
    ((XmlObjectBase) user).set(sources[i]);
}

After:

// O(n) once, then O(1) per element
List<XmlObject> existing = new ArrayList<>(m);
store.find_all_element_users(elemName, existing);

for (int i = 0; i < n; i++) {
    XmlObjectBase user = (i >= m) ? (XmlObjectBase) store.add_element_user(elemName)
                                   : (XmlObjectBase) existing.get(i);
    fun.accept(user, i);
}

Overall complexity for N-element array setter operations: O(n²) → O(n).

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.

2 participants