Skip to content

feat: Slight performance improvements#425

Open
kissifrot wants to merge 2 commits intocloudinary:masterfrom
kissifrot:feat/slight-perfs-improvements
Open

feat: Slight performance improvements#425
kissifrot wants to merge 2 commits intocloudinary:masterfrom
kissifrot:feat/slight-perfs-improvements

Conversation

@kissifrot
Copy link
Copy Markdown

@kissifrot kissifrot commented Apr 22, 2026

Brief Summary of Changes

Several small performance improvements targeting the most common hot paths: asset construction, URL generation, and API requests. No behaviour change.

  • BaseAsset::configuration() and AuthToken::configuration(): added a fast path that clones config sections directly when a Configuration instance is passed, avoiding a full new Configuration(...) rebuild (7-object init + serialize/deserialize cycle) on every asset creation.
  • Configuration::jsonSerialize() and BaseAsset::jsonSerialize(): replaced array_merge($json, $section) in loops with the union operator +=, equivalent for unique string-keyed arrays.
  • ApiClient::buildHttpClientConfig(): replaced array_merge_recursive with an explicit header merge + array_merge, avoiding nested-array side effects and unnecessary overhead.
  • AssetFinalizerTrait::finalizeSource() / finalizeVersion(): replaced preg_match calls with stripos/strncmp (preserving original case-sensitivity per call site); eliminated a redundant double call to publicId() in finalizeVersion().
  • AssetDescriptor::setSuffix(): replaced preg_match('/[.\/]/') with str_contains.

What does this PR address?

  • GitHub issue (Add reference - #XX)
  • Refactoring
  • New feature
  • Bug fix
  • Adds more tests

Are tests included?

  • Yes
  • No

Reviewer, please note:

  • BaseAsset::configuration() fast path uses clone instead of a serialize/deserialize round-trip. Independence from the source Configuration singleton is covered by the new testAssetConfigurationIsIndependentFromGlobalConfig test.
  • The finalizeSource() regex /^https?:\//i matches a single slash (e.g. http:/), not ://. The stripos replacement preserves this exact semantics.
  • finalizeVersion() used a case-sensitive regex; strncmp preserves that, while finalizeSource() used /i; stripos preserves that.
  • OAuth tests are extended to assert that User-Agent is preserved alongside Authorization — this is the regression guard for the buildHttpClientConfig() change.

Edit: I added a benchmark tool, below are the results:
10 000 iterations × 3 runs averaged on each branch (php tools/benchmark.php).

Scenario Before (master) After Gain
new Image($source) 1238 ms 21 ms x59.9
(string) new Image($source) 1417 ms 155 ms x9.1
$image->toUrl() (pre-built asset) 152 ms 132 ms -13%
new Image + setSuffix() 1409 ms 148 ms x9.5
(string) new Video($source) 1406 ms 153 ms x9.2
Configuration::jsonSerialize() 296 ms 290 ms -2%
new Image($source, $configArray) (array slow path) 648 ms 637 ms -2%

Main gain comes from the configuration() fast path: asset construction no longer triggers a full new Configuration(...) rebuild (7-object init + serialize/deserialize cycle) on every call.
The toUrl() row on a pre-built asset isolates URL generation improvements independently of construction overhead.

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I ran the full test suite before pushing the changes and all of the tests pass.

@kissifrot kissifrot force-pushed the feat/slight-perfs-improvements branch from 7ca7a61 to 184390a Compare April 22, 2026 11:17
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