Skip to content

Optimize properties_set to clone once instead of per property#26

Merged
veewee merged 1 commit into
mainfrom
feature/properties-set-clone-once
Mar 26, 2026
Merged

Optimize properties_set to clone once instead of per property#26
veewee merged 1 commit into
mainfrom
feature/properties-set-clone-once

Conversation

@veewee
Copy link
Copy Markdown
Owner

@veewee veewee commented Mar 26, 2026

Summary

properties_set() previously called property_set() per property, which cloned the object on every call. For an object with N properties, that's N clones and N ReflectedClass::fromObject() lookups.

Now clones once and sets all properties on the single clone directly using ReflectionProperty::setValue(). Dynamic properties (stdClass, AllowDynamicProperties) are handled via direct property assignment as a fallback.

Impact

For an object with 9 properties, properties_set cost drops from ~10us to ~5.5us (~45% faster). Measured in the php-soap/encoding benchmark suite where this is on the decode hot path.

Changes

  • Clone once at the start instead of per property
  • Iterate values and set via ReflectionProperty::setValue() directly
  • Handle dynamic properties inline (same behavior as property_set)
  • Empty values short-circuit (return original object)

Test plan

  • Full test suite passes (119 tests)
  • Psalm clean
  • CS fixer clean
  • Benchmarked in php-soap/encoding: -4% to -9% decode improvement

When setting multiple properties, the previous implementation cloned
the object N times (once per property_set call). Now clones once and
sets all properties on the single clone directly.

For an object with 9 properties, this roughly halves the cost of
properties_set (from ~10us to ~5.5us in php-soap/encoding benchmarks).
@veewee veewee merged commit 52731a6 into main Mar 26, 2026
18 checks passed
@veewee veewee deleted the feature/properties-set-clone-once branch March 26, 2026 17:31
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