You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Noticeably reduced performance with version 2 #244
Before proceeding, please update to latest version and test if the issue persists
Describe the bug in a sentence or two.
After upgrading to the new PHP SDK (from 1.x to 2.x) I noticed our 50th percentile drop considerably. I isolated the change and reverted back to 1.x and saw my response times go back to where they were previously. Unfortunately New Relic wasn't running correctly so I didn't manage to capture any better metrics.
I've opened this issue to see if anyone else has noticed similar issues. I would not have expected simply upgrading Cloudinary to have an a noticeable impact on response time. Additionally - we only use the PHP SDK for URL generation, not for uploading assets or anything, so it should be pretty negligible.
Issue Type (Can be multiple)
Build - Can’t install or import the SDK
Performance - Performance issues
Behaviour - Functions aren’t working as expected (such as generate URL)
Documentation - Inconsistency between the docs and behaviour
Other (Specify)
Operating System
Linux
Windows
macOS
All
Environment and Frameworks (fill in the version numbers)
I'm not entirely sure - I'm waiting on New Relic to get back up and running so I can crunch the numbers there, otherwise I'll see if I can replicate locally. I thought it was worth opening an issue just in case it was a more widespread problem. My use-case is literally just generating signed URLs so I'm surprised there would be any performance change.
We also face this issue. In some payloads we generate lots of image URLs (like several hundreds) and v2 seems to worsen performance considerably. We're also a bit confused why supposedly simple string transformation takes so much time...
I ended up biting the bullet and moving to v2 regardless because of the deprecation warnings from v1. Also realised that using signed vs non-signed URLs was a performance drain (makes sense in hindsight but disappointing nonetheless).
Both v2 and v3 have issues with excessive configuration setup and a lack of caching in that. Every call requires setting up all the configs again and again.
(forgive the AI generated code. I had it do this while I was working on other things)
All the test does it output 100 images (50 urls and 50 image tags)
You see, for 100 images it is calling safeImplode() 16k times. safeFilterFunc() calls strlen() 19k times - that's 190 times per image.
I use Cloudinary to output somewhere around 60 images per page. It takes longer to generate simple strings than it does to get the 48 products I'm displaying on the page from ElasticSearch.
Hi @joshua-bn. Thanks for flagging this. I have raised a ticket internally for us to look into this in more detail (ref SNI-8453) and we will let you know the outcome
Hi everyone — a quick update for anyone still subscribed to this issue.
We've just shipped a round of performance work that targets exactly the URL-generation hot path you flagged here. It builds on top of community contributions and analysis:
A proper deep-clone forConfiguration(and full test coverage for it) soAsset/Tagconstruction stops re-parsing the URL config on every call.
Memoization ofStringUtils::camelCaseToSnakeCase/snakeCaseToCamelCaseandClassUtils::getConstantsin the transformation builder (these were called tens of thousands of times per page on URL-heavy workloads).
TighterArrayUtilspaths (isAssoc→array_is_list,safeFilter/safeImplodeno longer allocate closures per call, etc.).
Releases
cloudinary/cloudinary_php3.1.3
cloudinary/transformation-builder-sdk2.1.4(pulled in automatically)
composer require cloudinary/cloudinary_php:^3.1.3
Numbers
Running @joshua-bn's exact 100-op workload (50 ×Media::fromParams+ 50 ×ImageTag::fromParams, with realistic transformations) on PHP 8.x:
per op
per 100-op pass
Before (3.1.2 + sdk 2.1.3)
~350 µs
~35 ms
After (3.1.3 + sdk 2.1.4)
~118 µs
~12 ms
Roughly3× faster end-to-endon that workload, with peak memory unchanged (~4 MB). Internally,Configuration::__constructcalls dropped from ~1,400 to1per workload, andsnakeCaseToCamelCasecalls from ~28,000 to ~1,400.
If you give 3.1.3 a try and still see something slow on your side, please drop a comment with a small repro (a snippet of how you're calling the SDK in the hot path) — happy to keep iterating.
Thanks again to @kissifrot and @joshua-bn for the contributions and analysis that made this round possible.
Activity
const-cloudinary commentedon Feb 19, 2021
@dwightwatson thank you for reporting the issue!
We did run some performance checks on the new version, for example we took this transformation:
https://cloudinary.com/documentation/php1_image_manipulation#adding_text_and_image_overlays
And ran it 10000 times in a loop.
On my computer it took:
v1 : 2.422s
v2: 2.657s
You can see some performance decrease of around 10% for just generating the transformations.
Is that the difference you are experiencing?
If you could provide more details, maybe send a few typical transformations that you use, we could investigate it further.
dwightwatson commentedon Feb 19, 2021
I'm not entirely sure - I'm waiting on New Relic to get back up and running so I can crunch the numbers there, otherwise I'll see if I can replicate locally. I thought it was worth opening an issue just in case it was a more widespread problem. My use-case is literally just generating signed URLs so I'm surprised there would be any performance change.
grubersjoe commentedon Oct 5, 2022
We also face this issue. In some payloads we generate lots of image URLs (like several hundreds) and v2 seems to worsen performance considerably. We're also a bit confused why supposedly simple string transformation takes so much time...
atdcloud commentedon Oct 10, 2022
@grubersjoe Just checking if you can share a code snippet so that we can test it on our end.
dwightwatson commentedon Oct 10, 2022
I ended up biting the bullet and moving to v2 regardless because of the deprecation warnings from v1. Also realised that using signed vs non-signed URLs was a performance drain (makes sense in hindsight but disappointing nonetheless).
joshua-bn commentedon Aug 2, 2025
Both v2 and v3 have issues with excessive configuration setup and a lack of caching in that. Every call requires setting up all the configs again and again.
I did some profiling with xdebug profiler. If you've never used it, it's very simple https://xdebug.org/docs/profiler. Just checkout this repo: https://github.com/joshua-bn/Cloudinary-PHP-SDK-Analysis and then run the docker commands to get the output. Run your cachegrind tool of choice and view the output.
(forgive the AI generated code. I had it do this while I was working on other things)
All the test does it output 100 images (50 urls and 50 image tags)
You see, for 100 images it is calling safeImplode() 16k times. safeFilterFunc() calls strlen() 19k times - that's 190 times per image.
I use Cloudinary to output somewhere around 60 images per page. It takes longer to generate simple strings than it does to get the 48 products I'm displaying on the page from ElasticSearch.
dannyv-cloudinary commentedon Aug 2, 2025
Hi @joshua-bn. Thanks for flagging this. I have raised a ticket internally for us to look into this in more detail (ref SNI-8453) and we will let you know the outcome
kissifrot commentedon Apr 22, 2026
Hello, do you have any news on this issue ?
dannyv-cloudinary commentedon Apr 22, 2026
Unfortunately not. This is in our backlog, and when there is an update to share, someone from Cloudinary will update this ticket
kissifrot commentedon Apr 22, 2026
I had a try on #425 🤞
const-cloudinary commentedon Apr 26, 2026
Hi everyone — a quick update for anyone still subscribed to this issue.
We've just shipped a round of performance work that targets exactly the URL-generation hot path you flagged here. It builds on top of community contributions and analysis:
feat: Slight performance improvements(deep-clone fast path forConfigurationand a few smaller wins on the URL-build path).On top of those, we landed:
Configuration(and full test coverage for it) soAsset/Tagconstruction stops re-parsing the URL config on every call.StringUtils::camelCaseToSnakeCase/snakeCaseToCamelCaseandClassUtils::getConstantsin the transformation builder (these were called tens of thousands of times per page on URL-heavy workloads).ArrayUtilspaths (isAssoc→array_is_list,safeFilter/safeImplodeno longer allocate closures per call, etc.).Releases
composer require cloudinary/cloudinary_php:^3.1.3cloudinary/cloudinary_php3.1.3cloudinary/transformation-builder-sdk2.1.4 (pulled in automatically)Numbers
Running @joshua-bn's exact 100-op workload (50 ×
Media::fromParams+ 50 ×ImageTag::fromParams, with realistic transformations) on PHP 8.x:Roughly 3× faster end-to-end on that workload, with peak memory unchanged (~4 MB). Internally,
Configuration::__constructcalls dropped from ~1,400 to 1 per workload, andsnakeCaseToCamelCasecalls from ~28,000 to ~1,400.If you give 3.1.3 a try and still see something slow on your side, please drop a comment with a small repro (a snippet of how you're calling the SDK in the hot path) — happy to keep iterating.
Thanks again to @kissifrot and @joshua-bn for the contributions and analysis that made this round possible.