Skip to content

Noticeably reduced performance with version 2 #244

Description

@dwightwatson

Bug report for Cloudinary PHP SDK

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.

image

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)

  • PHP Cloudinary SDK version - 2.0.2
  • PHP Version - 8.0.2
  • Framework (Laravel, Symphony, etc) - 8.27.0

Activity

  1. const-cloudinary commented on Feb 19, 2021

    @const-cloudinary
    Member

    @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.

  2. dwightwatson commented on Feb 19, 2021

    @dwightwatson
    Author

    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.

  3. grubersjoe commented on Oct 5, 2022

    @grubersjoe

    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...

  4. atdcloud commented on Oct 10, 2022

    @atdcloud

    @grubersjoe Just checking if you can share a code snippet so that we can test it on our end.

  5. dwightwatson commented on Oct 10, 2022

    @dwightwatson
    Author

    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).

  6. joshua-bn commented on Aug 2, 2025

    @joshua-bn

    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)

    Image

    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.

  7. dannyv-cloudinary commented on Aug 2, 2025

    @dannyv-cloudinary

    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

  8. kissifrot commented on Apr 22, 2026

    @kissifrot
    Contributor

    Hello, do you have any news on this issue ?

  9. dannyv-cloudinary commented on Apr 22, 2026

    @dannyv-cloudinary

    Unfortunately not. This is in our backlog, and when there is an update to share, someone from Cloudinary will update this ticket

  10. kissifrot commented on Apr 22, 2026

    @kissifrot
    Contributor

    I had a try on #425 🤞

  11. const-cloudinary commented on Apr 26, 2026

    @const-cloudinary
    Member

    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:

    On top of those, we landed:

    • A proper deep-clone for Configuration (and full test coverage for it) so Asset/Tag construction stops re-parsing the URL config on every call.
    • Memoization of StringUtils::camelCaseToSnakeCase / snakeCaseToCamelCase and ClassUtils::getConstants in the transformation builder (these were called tens of thousands of times per page on URL-heavy workloads).
    • Tighter ArrayUtils paths (isAssoc → array_is_list, safeFilter / safeImplode no longer allocate closures per call, etc.).

    Releases

    • cloudinary/cloudinary_php 3.1.3
    • cloudinary/transformation-builder-sdk 2.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

    Roughly 3× faster end-to-end on that workload, with peak memory unchanged (~4 MB). Internally, Configuration::__construct calls dropped from ~1,400 to 1 per workload, and snakeCaseToCamelCase calls 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions