Skip to content

Cheaper xsi:nil checks and value reads on decode - #85

Merged
veewee merged 4 commits into
php-soap:element-lookupfrom
veewee:perf-cheaper-decode-reads
Oct 16, 2026
Merged

veewee merged 4 commits into
php-soap:element-lookupfrom
veewee:perf-cheaper-decode-reads

Conversation

@veewee

@veewee veewee commented Oct 15, 2026 •

Copy link
Copy Markdown
Member
Q A
Type improvement
BC Break no
Fixed issues

Stacked on #80.

Summary

Decoding called Xmlns::xsi() for every element it checked for xsi:nil, which builds a new object on every call, and read every element value through Locator\Node\value($element, string()). That function reads substitutedNodeValue and coerces it with Psl, but on a Dom\Element that property is already a non-nullable string.

OptionalElementEncoder::iso() now resolves the xsi namespace once per iso, and ElementValueReader reads substitutedNodeValue directly. Each change is its own commit.

Same output

The namespace string and the value read are the same as before, so decoded values and exceptions cannot change. The removed coercion could not fail, because the property is typed string. The decoded results of the 3MB workloads have the same sha1 before and after.

Stacked on #80

This branch is based on #80, which deletes DocumentToLookupArrayReader, so the diff only touches OptionalElementEncoder and ElementValueReader. I left ElementLookup::text() alone because it only runs for the _ text value. I left XsiTypeDetector alone because #82 rewrites that line.

Speed

Median of 3 interleaved rounds on the same machine, with ext-soap as the noise reference.

workload main this PR
3MB decode sparse, stdClass 0.491 s 0.469 s (-4.6%)
3MB decode sparse, classmap 0.911 s 0.901 s (-1.1%)
3MB decode dense, stdClass 0.271 s 0.259 s (-4.3%)
3MB decode dense, classmap 0.327 s 0.317 s (-3.3%)
DecodeBench literal x500 31.75 ms 29.56 ms (-6.9%)
DecodeBench encoded x500 47.51 ms 48.12 ms (+1.3%)
ext-soap decode literal x500 5.37 ms 5.41 ms (+0.7%)

The gain is small and only on decode. Encode stays within 3% either way.

Summary by CodeRabbit

  • Refactor
    • Updated XML decoding internals while preserving existing handling of nil elements and text values.
    • XML elements continue to produce the same decoded results, with no changes to the public interface.

Hoist per property type meta out of the object loops
Xmlns::xsi() builds a new object on every call. OptionalElementEncoder now resolves it once per iso, and DocumentToLookupArrayReader compares against a class constant.
Locator\Node\value() reads substitutedNodeValue and coerces it to a string, which it already is on a Dom\Element. Reading the property skips the function call and the Psl coercion.
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0506687b-414f-411b-af7d-cb38f2fe576c
📥 Commits

Reviewing files that changed from the base of the PR and between 403a479 and 353a61c.

📒 Files selected for processing: 3
  • src/Encoder/OptionalElementEncoder.php
  • src/Xml/Reader/DocumentToLookupArrayReader.php
  • src/Xml/Reader/ElementValueReader.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

The changes update XSI namespace lookups for nil attributes and pass substituted XML node values directly to encoder and ISO conversion methods.

Changes: XML decoding

Layer / File(s) Summary
XSI nil-attribute lookups
src/Encoder/OptionalElementEncoder.php, src/Xml/Reader/DocumentToLookupArrayReader.php
The optional-element decoder captures the XSI namespace for its nil check. The document reader uses a private namespace constant for its nil check. Both retain the existing nil="true" behavior.
Element value conversion
src/Xml/Reader/ElementValueReader.php
forEncoder and forIso pass Element::substitutedNodeValue directly to their conversion methods.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 353a6

XML decoding retains its prior nil handling and entity-substituted values for supported DOM elements. No concrete behavior regression is indicated, so the change appears ready to merge under normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main changes: reducing the cost of xsi:nil checks and element value reads during decoding.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…per-decode-reads

# Conflicts:
#	src/Xml/Reader/DocumentToLookupArrayReader.php
@veewee
veewee changed the base branch from main to element-lookup October 16, 2026 05:43
@veewee
veewee merged commit 27fc514 into php-soap:element-lookup Oct 16, 2026
13 checks passed
@veewee
veewee deleted the perf-cheaper-decode-reads branch October 16, 2026 08:49
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