WordPress.org

Make WordPress Core

Opened 2 years ago

Closed 2 years ago

#43112 closed enhancement (invalid)

set_transient uses object-cache as storage instead of cache layer

Reported by: batooo Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.9.1
Component: Cache API Keywords:
Focuses: Cc:
PR Number:

Description

set_transient() function is using object-cache as storage instead as caching layer.
Using APCu as an object-cache which is a PHP in-process storage leads to high CPU and very slow loading time. PHP processes have a lifetime and also can be restarted by many factors e.g server reload, PHP upgrade, ini change. Each time PHP process is restarted, APCu storage is empty.

High CPU use case:
Because transient storage will be empty on PHP restart, the site needs to recalculate many operations each time PHP process is restarted.

Very slow loading time use case:
All external API requests like "WordPress auto update checks" will be executed every time PHP is restarted.
I have a site with fast velocity minify & alidropship plugins and because those plugins use HTTP API + add the WordPress checks, sometimes even leads to server-timeout.

Object-cache as its name should be used for caching not as storage.

Change History (6)

#1 in reply to: ↑ description ; follow-up: @dimadin
2 years ago

If you want to have “persistent” transients, than there are libraries that you can use to save temporary data in database instead of in object cache. For example, my own WP_Temporary, or newly released Async Transients.

In case of WP_Temporary, you would use WP_Temporary::set( $transient, $value, $expiration ); instead of set_transient( $transient, $value, $expiration );. Advantage here is that even if object cache is purged for whatever reason, your data is still available from database until it expires. Disadvantage is that you can use that only in your own code for your own caches, other transients will still be saved in object cache only. You can code workaround to force that data in database too, but I am not sure will it degrade performance for some cases.

Using APCu as an object-cache which is a PHP in-process storage leads to high CPU and very slow loading time.

I am not sure what you want to say with this, but note that when you turn on object caching, many other data is stored there, not just transients, post objects, taxonomy terms, comments, users, queries etc.

#2 in reply to: ↑ 1 ; follow-up: @batooo
2 years ago

Not a solution as you said, "Disadvantage is that you can use that only in your own code for your own caches, other transients will still be saved in object cache only.".

About slow loading or high CPU, imagine 10 external API requests each time PHP is restarted or imagine doing some CPU intense job each time PHP is restarted instead of every 24 hours.

What`s the point of using object-cache as storage for transient API?

Replying to dimadin:

If you want to have “persistent” transients, than there are libraries that you can use to save temporary data in database instead of in object cache. For example, my own WP_Temporary, or newly released Async Transients.

In case of WP_Temporary, you would use WP_Temporary::set( $transient, $value, $expiration ); instead of set_transient( $transient, $value, $expiration );. Advantage here is that even if object cache is purged for whatever reason, your data is still available from database until it expires. Disadvantage is that you can use that only in your own code for your own caches, other transients will still be saved in object cache only. You can code workaround to force that data in database too, but I am not sure will it degrade performance for some cases.

Using APCu as an object-cache which is a PHP in-process storage leads to high CPU and very slow loading time.

I am not sure what you want to say with this, but note that when you turn on object caching, many other data is stored there, not just transients, post objects, taxonomy terms, comments, users, queries etc.

Last edited 2 years ago by batooo (previous) (diff)

#3 in reply to: ↑ 2 ; follow-ups: @dimadin
2 years ago

Replying to batooo:

Then you should just code wrapper around transient functions to force it to store data in database instead of object cache like it is now, and see if it will bring performance improvements.

#4 in reply to: ↑ 3 @batooo
2 years ago

Replying to dimadin:
Im not really a PHP developer and it will be a nice if you give me simple sample, then I`ll do my research.

The point is to override those functions, something like that.

Replying to batooo:

Then you should just code wrapper around transient functions to force it to store data in database instead of object cache like it is now, and see if it will bring performance improvements.

Last edited 2 years ago by batooo (previous) (diff)

#5 in reply to: ↑ 3 @batooo
2 years ago

Replying to dimadin:
I hope you don`t mean modifying the WP core file: /wp-includes/option.php

Replying to batooo:

Then you should just code wrapper around transient functions to force it to store data in database instead of object cache like it is now, and see if it will bring performance improvements.

#6 @dd32
2 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

Hi @batooo and welcome to Trac.

The transient functions are specifically cache functions, and are not designed to be used for storage.
WordPress has three main "option" type stores:

  • Options. Persistent data stored in the Database and cached in memory
  • Object Cache. Non-persistent data not stored in the database and only in memory if enabled.
  • Transients. Non-persistent data backed by either the Object cache (if enabled) or the Database otherwise.

Each storage option offers different levels of persistence, depending on the actual need of the code. It's expected that Transients will remain available for 0 ~ $timeout seconds, and it's by design that they may be purged from memory instantly.

If you choose to utilise PHP's APCu functionalities, you should expect the transient & object cache data to be dumped upon restart. If you choose to use Memcache or Redis as the object cache, the data will be there until purged or those services are restarted/etc.
The time to retrieve such items from the normal key-value object caches is generally faster than fetching from MySQL directly (or allowing MySQL to handle other queries)

Since this is by design, I'm closing this as invalid but hopefully the above will help you understand the uses of the various storage options.

Note: See TracTickets for help on using tickets.