You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by "pjfanning (via GitHub)" <gi...@apache.org> on 2026/09/03 18:08:34 UTC
[PR] Reduce the per-run work done when opening a Word document [poi]
pjfanning opened a new pull request, #1243:
URL: https://github.com/apache/poi/pull/1243
Opening a .docx eagerly constructs an `XWPFParagraph` for every paragraph and an `XWPFRun` for every run, so anything done per run in those constructors is paid by every document. Three things were.
### `XWPFRun` ran an XPath query on every run
The constructor built a ~200-character query string by concatenation and called `r.selectPath(...)` looking for `./mc:AlternateContent/mc:Choice/w:drawing`, on every run — while almost every real run is plain text with no picture content at all.
The two query strings are now `static final` constants (they were built from compile-time constants, so they are byte-identical), and the whole picture/drawing block is skipped unless the run can actually hold such content: `sizeOfPictArray() > 0 || sizeOfDrawingArray() > 0`, or a direct `mc:AlternateContent` child found by a plain DOM sibling scan.
The guard is a strict superset of the three sources that feed `pictTextObjs`. The XPath is anchored at `./mc:AlternateContent`, i.e. direct children only, and the DOM scan checks exactly those children by namespace and local name — so the case where `selectPath` matches while both `sizeOf` counts are zero still passes the guard. When the guard is false all three sources are provably empty, so `pictureText` would have been `""` and both loops no-ops.
### `XWPFParagraph` walked every run's children with a cursor
After building the runs it opened an `XmlCursor` and ran `selectPath("child::*")` over the children of every run to find `CTFtnEdnRef` footnote references, which are rare. Checked against the generated schema: `CTFtnEdnRef` occurs in `CTR` only as `w:footnoteReference` and `w:endnoteReference`, so the walk is now skipped when the run has neither.
The cursor walk itself is deliberately unchanged rather than replaced with the typed accessors, because `getFootnoteReferenceArray()` + `getEndnoteReferenceArray()` would group all footnote refs before all endnote refs and change the append order for a run that mixes both.
### `XWPFTable` parsed every cell twice
`processCTRow` constructed a full `XWPFParagraph` — and therefore all its `XWPFRun`s — for every paragraph of every cell, purely to precompute the `text` field, then discarded the objects. But the line above it already did `new XWPFTableRow(row, this)`, which builds an `XWPFTableCell` per cell, each of which already builds an `XWPFParagraph` per paragraph. Every table cell was being parsed twice on open. It now reads the paragraphs from the row it just built.
Same set and order (`XWPFTableRow` uses `ctRow.getTcArray()`; a cell's paragraphs are its direct `w:p` children in document order), and both paragraph sets resolve to the same `XWPFDocument`, so `getText()` is unchanged. The drawing-id reservations that the discarded objects performed were duplicates of ones the cell paragraphs had already made.
I did not make `getText()` lazy: `text` is captured at construction today and never updated by `addRow`/`createRow`/`setText`, so a lazy version would start reflecting later mutations, and `text` is a `protected` field an out-of-tree subclass could read.
All 313 `org.apache.poi.xwpf.*` tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org
Re: [PR] Reduce the per-run work done when opening a Word document [poi]
Posted by "pjfanning (via GitHub)" <gi...@apache.org>.
pjfanning merged PR #1243:
URL: https://github.com/apache/poi/pull/1243
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org