Problem/Motivation

The Drupal\Core\KeyValueStore\DatabaseStorage uses a configurable serializer to store PHP objects. This serializer is injected as a service in core. The pre-configured serializer used there Drupal\Component\Serialization\PhpSerialize:

  keyvalue.database:
    class: Drupal\Core\KeyValueStore\KeyValueDatabaseFactory
    arguments: ['@serialization.phpserialize', '@database']
  serialization.phpserialize:
    class: Drupal\Component\Serialization\PhpSerialize

This architecture allows contrib modules like https://www.drupal.org/project/igbinary to swap the serializer. For example igbinary shrinks the size of larger serialized PHP objects to one third without losing any performance. (In some cases the performance is increased as well.)

Having this kind of memory saving would be a huge benefit for all kind of drupal caches that store serialized PHP objects, especially if there using in memory solutions like memcache. Systems like redis or even the database will benefit from igbinary as well.

Unfortunately the Drupal\Core\Cache\DatabaseBackend and the Drupal\Core\Cache\MemoryBackend use a hard-coded PHP serialization. Therefore the could not be easily improved by modules like https://www.drupal.org/project/igbinary

Proposed resolution

Follow the pattern of Drupal\Core\KeyValueStore\DatabaseStorage and Drupal\Core\KeyValueStore\DatabaseStorageExpirable and inject the serialize as a service to the Drupal\Core\Cache\DatabaseBackend.

The default configuration in core should then "remain" as it is and inject Drupal\Component\Serialization\PhpSerialize.

Even if this improvement makes sense for the Drupal\Core\Cache\MemoryBackend as well, @catch decided to not modify it in core. This backend is heavily used in the tests which will be more complicated afterwards. Therefore the igbinary contrib module will provide it's own backend as drop-in replacement.

As proposed by @berdir we introduce a "new" service serialization.objectaware.default that is in core just an alias for serialization.phpserialize. The redis module will leverage this one as well as soon as this patch gets committed. This new default service eases the task for the modules like igbinary to switch (most of) the serilaizers system wide.

Remaining tasks

Review the existing patch.

User interface changes

None.

API changes

Similar to Drupal\Core\KeyValueStore\KeyValueDatabaseFactory and Drupal\Core\KeyValueStore\DatabaseStorage the constructor of Drupal\Core\Cache\DatabaseBackend an its factory need to be prepared for dependency injection.
In addition we define a new interface Drupal\Component\Serialization\ObjectAwareSerializationInterface that just extends Drupal\Component\Serialization\SerializationInterface to clearly indicate that implementing Serializers are suitable for PHP Object serialization.

Old:

DatabaseBackendFactory::__construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider);
DatabaseBackend::__construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin);

New:

interface ObjectAwareSerializationInterface extends SerializationInterface {}

DatabaseBackendFactory::__construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, ObjectSerializationInterface $serializer = NULL);
DatabaseBackend::__construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin, ObjectSerializationInterface $serializer = NULL);

These API changes don't break BC!

Data model changes

None.

CommentFileSizeAuthor
#209 839444_10.1.5.patch13.31 KBmkalkbrenner
#208 839444_10.1.5.patch12.34 KBmkalkbrenner
#205 839444_10.x.patch13.32 KBmkalkbrenner
#203 839444_10.0.x.patch12.59 KBmkalkbrenner
#202 839444_10.1.x.patch12.59 KBmkalkbrenner
#200 839444-nr-bot.txt159 bytesneeds-review-queue-bot
#198 839444_no_depencies_9.5.x.patch13.33 KBmkalkbrenner
#197 839444_no_deprecation.patch11.6 KBmkalkbrenner
#196 839444_no_deprecation.patch11.86 KBmkalkbrenner
#194 839444-191.patch13.33 KBquietone
#191 839444-191.patch13.33 KBandypost
#191 interdiff.txt3.57 KBandypost
#188 interdiff_186_188.txt593 byteswells
#188 839444-188.patch12.59 KBwells
#186 interdiff_184_186.txt561 byteskapilv
#186 839444-186.patch13.5 KBkapilv
#184 839444-184.patch13.5 KBsokru
#184 interdiff-183-184.txt519 bytessokru
#183 interdiff_182-183.txt677 bytessuresh prabhu parkala
#183 839444-183.patch13.46 KBsuresh prabhu parkala
#182 839444-182.patch13.74 KBravi.shankar
#174 839444-174-9.0.x.patch13.73 KBgnunes
#174 interdiff-173-174-9.0.x.txt575 bytesgnunes
#173 interdiff-171-173-9.0.x.txt2.46 KBgnunes
#173 839444-173-9.0.x.patch13.98 KBgnunes
#171 interdiff-167-171-9.0.x.txt1.72 KBgnunes
#171 839444-171-9.0.x.patch15.48 KBgnunes
#167 interdiff-165-167--bc-bootstrap-service-9.0.x.txt1.07 KBgnunes
#167 interdiff-165-167--bc-bootstrap-service-8.9.x.txt1.33 KBgnunes
#167 839444-167-9.0.x.patch15.97 KBgnunes
#167 839444-167-8.9.x.patch15.97 KBgnunes
#167 839444-167--merge-bootstrap-definitions-9.0.x.patch16.77 KBgnunes
#167 839444-167--merge-bootstrap-definitions-8.9.x.patch16.77 KBgnunes
#167 839444-167--bc-bootstrap-service-9.0.x.patch18.24 KBgnunes
#167 839444-167--bc-bootstrap-service-8.9.x.patch18.5 KBgnunes
#165 interdiff-merge-bootstrap-definitions.txt1.01 KBhchonov
#165 839444-165--merge-bootstrap-definitions.patch16.77 KBhchonov
#165 interdiff-bc-bootstrap-service.txt2.23 KBhchonov
#165 839444-165--bc-bootstrap-service.patch18.2 KBhchonov
#165 interdiff-158-165.txt4.46 KBhchonov
#165 839444-165.patch15.97 KBhchonov
#158 interdiff-155-158.txt1.07 KBgease
#158 839444-158.patch15.97 KBgease
#155 839444-155.patch14.74 KBgease
#153 839444-153.patch14.74 KBandypost
#153 interdiff.txt2.1 KBandypost
#151 839444-151.patch14.63 KBandypost
#151 interdiff.txt2.35 KBandypost
#149 839444-149.patch14.49 KBandypost
#149 interdiff.txt1.78 KBandypost
#147 839444-147.patch14.42 KBandypost
#147 interdiff.txt4.18 KBandypost
#137 839444-137.interdiff.txt5.42 KBclaudiu.cristea
#137 839444-137.patch14.27 KBclaudiu.cristea
#134 839444-134.patch12.29 KBclaudiu.cristea
#134 839444-134.interdiff.txt1.61 KBclaudiu.cristea
#128 839444-128.patch12.03 KBtstoeckler
#118 interdiff-116-119.txt1.03 KBkfritsche
#118 839444-118.patch12.08 KBkfritsche
#116 839444_object_aware_serialization_service_for_cache_database_backend-116.patch11.05 KBkfritsche
#113 839444_object_aware_serialization_service_for_cache_database_backend-113.patch10.5 KBhchonov
#99 839444_object_aware_serialization_service_for_cache_database_backend-99.patch10.48 KBmkalkbrenner
#99 97-99-interdiff.txt832 bytesmkalkbrenner
#97 839444_object_aware_serialization_service_for_cache_database_backend-97.patch10.48 KBmkalkbrenner
#97 86-97-interdiff.txt8.11 KBmkalkbrenner
#86 839444_object_aware_serialization_service_for_cache_database_backend-86.patch10.46 KBmkalkbrenner
#86 83-86-interdiff.txt2.88 KBmkalkbrenner
#83 839444_object_aware_serialization_service_for_cache_database_backend-83.patch7 KBmkalkbrenner
#83 81-83-interdiff.txt461 bytesmkalkbrenner
#81 839444_object_aware_serialization_service_for_cache_database_backend-81.patch7 KBmkalkbrenner
#81 71-81-interdiff.txt7.3 KBmkalkbrenner
#71 839444_object_aware_serialization_service_for_cache_database_backend-71.patch10.3 KBmkalkbrenner
#71 63-71-interdiff.txt26.19 KBmkalkbrenner
#63 839444_serialization_service_for_cache_database_and_memory_backends-63.patch36.43 KBmkalkbrenner
#63 58-63-interdiff.txt5.97 KBmkalkbrenner
#58 839444_serialization_service_for_cache_database_and_memory_backends-58.patch35.34 KBmkalkbrenner
#58 56-58-interdiff.txt3.28 KBmkalkbrenner
#56 839444_serialization_service_for_cache_database_and_memory_backends-56.patch32.61 KBmkalkbrenner
#54 839444_serialization_service_for_cache_database_and_memory_backends-54.patch32.55 KBmkalkbrenner
#54 48-54-interdiff.txt572 bytesmkalkbrenner
#48 839444_serialization_service_for_cache_database_and_memory_backends-48.patch32.54 KBmkalkbrenner
#48 47-48-interdiff.txt950 bytesmkalkbrenner
#47 839444_serialization_service_for_cache_database_and_memory_backends-47.patch32.8 KBmkalkbrenner
#47 45-47-interdiff.txt1.05 KBmkalkbrenner
#45 839444_serialization_service_for_cache_database_and_memory_backends-45.patch31.61 KBmkalkbrenner
#45 43-45-interdiff.txt1.75 KBmkalkbrenner
#43 839444_serialization_service_for_cache_database_and_memory_backends-43.patch31.27 KBmkalkbrenner
#43 41-43-interdiff.txt1.66 KBmkalkbrenner
#41 839444_serialization_service_for_cache_database_and_memory_backends-41.patch29.36 KBmkalkbrenner
#41 39-41-interdiff.txt2.77 KBmkalkbrenner
#39 839444_serialization_service_for_cache_database_and_memory_backends-39.patch27.82 KBmkalkbrenner
#39 36-39-interdiff.txt6.25 KBmkalkbrenner
#36 839444_serialization_service_for_cache_database_and_memory_backends-36.patch20.77 KBmkalkbrenner
#36 34-36-interdiff.txt3.96 KBmkalkbrenner
#34 839444_serialization_service_for_cache_database_and_memory_backends-34.patch16.25 KBmkalkbrenner
#34 30-34-interdiff.txt3.36 KBmkalkbrenner
#30 839444_serialization_service_for_cache_database_and_memory_backends-30.patch12.26 KBmkalkbrenner
#30 27-30-interdiff.txt5.88 KBmkalkbrenner
#27 839444_serialization_service_for_cache_database_backend-27.patch5.82 KBmkalkbrenner
#27 22-27-interdiff.txt814 bytesmkalkbrenner
#24 839444_serialization_service_for_cache_database_backend-24.patch5.64 KBmkalkbrenner
#24 22-24-interdiff.txt629 bytesmkalkbrenner
#22 839444_serialization_service_for_cache_database_backend.patch4.93 KBmkalkbrenner
#9 drupal_convert_serialize_to_json.patch49.6 KBkeichee
#7 test.php_.txt6.28 KBdamien tournoud
#6 bench.png171.44 KBkeichee
#5 drupal_json_encode_decode.patch48.72 KBkeichee

Issue fork drupal-839444

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jbrown’s picture

Version: 7.x-dev » 8.x-dev

This is D8 material.

ogi’s picture

subscribe

rbayliss’s picture

I lhad no idea json_encode() was that much faster. Still, json_encode's inability to restore objects as anything but stdClass makes this less worthwhile IMO, especially now that we have the class registry. Maybe it's worth looking into alternative serialization for specific places we store large simple arrays though. I'm looking at drupal_get_schema() and _theme_load_registry(). We can always json_encode() (or whatever function) the data before passing it into cache_set() as long as we know how to decode it on the way back out.

damien tournoud’s picture

I have done some limited benchmark with serialize / igserialize / json_encode on PHP 5.3, and it seems that serialize is not slow anymore.

keichee’s picture

Assigned: Unassigned » keichee
StatusFileSize
new48.72 KB

please download the benchmark at
https://github.com/jbergstroem/instabench

please download the php version PHP 5.4.0alpha1 (latest version) in PHP

The latter handles most of the PHP data structures, while the former only handles Javascript arrays (a type of data that doesn't exist in PHP) and Javascript plain objects (that are relatively similar to PHP arrays).
> i think there are two PHP data structures, arrays and objects which json handles better

The latter is binary safe, while the former only handles valid Unicode strings (try json_encode(chr(255)), for example
> if there will be error in the code, i will later patch all invalid unicode strings to json friendly version

please do see the benchmark as serialize are intensively used by drupal, if this benchmark is correct, drupal will be 2.7x faster

D:\php-5.4.0alpha1-Win32-VC9-x86>php.exe ..\nginx-1.0.4\html\jbergstroem-instabe
nch-5f828f9\test.php
InstaBench 0.1 (PHP 5.4.0alpha1)

Benchmarking results (10000 iterations)
=======================================
   serialize: 7507ms (baseline)
  var_export: 19096ms (0.4x slower)
 json_encode: 2794ms (2.7x faster)

i definitely want to choose 2.7x faster drupal and later problem unicode strings like chr(255)
how about others?

please check attached patch if will succeed, many thanks

others please post your benchmark, and let this patch succeed!
imagine, almost 3x speed than the latter. wow!

keichee’s picture

StatusFileSize
new171.44 KB

more benchmarks, raw screenshots attached

json_encode is 
2.3x
3.5x
2.0x
3.1x

faster than serialize 

imagine up to 4x speed of drupal than the latter, wow!
please test my patch, many thanks!

damien tournoud’s picture

StatusFileSize
new6.28 KB

This is just a stupid benchmark. Take anything non trivial (like the attached - we serialize a node generated by Devel Generate), and you will get:

InstaBench 0.1 (PHP 5.3.4)

Benchmarking results (10000 iterations)
=======================================
   serialize: 781ms (baseline)
  var_export: 2259ms (0.3x slower)
 json_encode: 1354ms (0.6x slower)
damien tournoud’s picture

You can even better results when testing the unserialize . serialize roundtrip.

keichee’s picture

Status: Active » Needs review
Issue tags: -Performance
StatusFileSize
new49.6 KB

can you review my patch if it will return success?
my goal is to change serialize/unserialize to drupal_json_encode/ drupal_json_decode

to make encoded versions in blobs in database more readable and more html5 and javascript friendly
against serialize versions.

there are no native serialize out there, but json can be directly readable to javascript.

added some tests in simpletest so it will return success.

Status: Needs review » Needs work

The last submitted patch, drupal_convert_serialize_to_json.patch, failed testing.

sun’s picture

#921300: Use json_encode/decode() instead of un/serialize() has been marked as duplicate.

Lessons learned from that issue: The problem with JSON is that it doesn't allow for mixed non-scalar data types. It also does not support 1) serialized class instances and 2) PHP references.

But Drupal stores a lot of serialized data containing mixed data types. The most obvious use-case is:

$form_state = array();
$form_state['values'] = array(...);
$form_state['node'] = stdClass $node;

And that's just one of many examples throughout Drupal core. That's why I stopped working on aforementioned issue.

The only viable option I could see would be to introduce an optional flag, in particular for cache_set(), that would allow the caller to say "I absolutely and definitely know that this data is an array and doesn't contain any objects or references, so you may use JSON for serialization." -- combined with a new or revised "serialized" schema column that tells how to unserialize for each record.

star-szr’s picture

Closed #1340260: Support for igbinary as a duplicate of this issue.

quicksketch’s picture

Status: Needs work » Active

The topic of this issue doesn't really match the patch in #11, so I'm moving this back to active. I also get the feeling that the performance of unserialize() may depend heavily on which version of PHP you're running. In 2010, PHP apparently made an adjustment to HEAD that sped up unserialize signficantly. In that issue at least they say it couldn't be included in PHP 5.3 for compatibility reasons, so I'm guessing it's only in PHP 5.4.

I was doing research into the igbinary serializer today and found this issue. Against PHP 5.3.22 I didn't find igbinary serialize to be that much faster. According to XHProf, igbinary was only marginally faster (with its "compact_strings" option turned on).

However, the *size* of the serialized data was significantly reduced. Most entries in the cache_* tables were reduced by about half, and entries that had a lot of redundant data (such as cache_form) reduced entries to a 1/3 - 1/4 the original size. Larger reductions are seen the larger the form being serialized.

So overall, yay, I think I like igbinary_serialize() and igbinary_unserialize(). Combined with the reduction in overhead of transferring this data to the database or memcache, you could get some modest improvements.

However my opinion on this is that making the serializer customizable (per this issue title) is unnecessary. unserialize() is already getting faster in newer versions of PHP (apparently, I don't have numbers on that), but more over, if you want to replace the largest uses of serialize/unserialize, you can do so already by providing a custom cache back-end. Alternatively I think it would be a great idea for existing cache backends (Redis, Memcache, etc.) to support using igbinary_serialize() automatically if it is available. The largest unserialization strings we have (and most of them) are coming from cache_get(). Since this is already swappable, I don't think any additional effort is required on the part of core.

thmnhat’s picture

Issue summary: View changes

Hey, sorry for digging this up but has anyone had solution for igbinary support? I'm thinking about swappable handler also, just like quicksketch mentioned above but still don't know how to implement it. Because when the cache is built with native serializer, and right after that we get and set new cache with igbinary, everything will be broken

I already made a copy here https://github.com/in2pire/drupal-igbinary just for research. Replaced all serialize() and unserialize() with igbinary functions.

Hope that we can find some ways to add the support for igbinary soon.

grom358’s picture

I was talking to Pierre Joye at DrupalSouth and he mentioned we should not be using serialize due to a) it can break between PHP versions. b) its not secure. After this discussion it should perhaps be raised to higher priority.

Anonymous’s picture

See the contributed module for Drupal 7: https://www.drupal.org/project/igbinary_cache

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

DaPooch’s picture

igbinary_cache is a step in the right direction but there's a lot of other contributed modules that use serialize/unserialize function calls directly that could benefit. Truthfully it's unfortunate that there's not a direct drop-in replacement on the PHP level to handle this. Seems like it would make the most sense to do it there so that the syntax for serialize and unserialize could be independant of the actual library doing the serialization. They already do this with the session storage option would be nice to expand it into the functions themselves too.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

hchonov’s picture

Version: 8.2.x-dev » 8.3.x-dev
mkalkbrenner’s picture

I created https://www.drupal.org/project/igbinary
It enables igbinary for Drupal's key value stores.

The next step would be to create a set of core patches to delegate serialization to services implementing Drupal\Component\Serialization\SerializationInterface instead of calling serialize() and unserialize() directly. In core they should leverage the PHPSerialize by default, just like the key value stores.

mkalkbrenner’s picture

Assigned: keichee » Unassigned
Status: Active » Needs review
StatusFileSize
new4.93 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

StatusFileSize
new629 bytes
new5.64 KB

Drupal-like hard-coded dependency injection :-(

mkalkbrenner’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new814 bytes
new5.82 KB

Sorry, #24 was incomplete.

hchonov’s picture

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new5.88 KB
new12.26 KB
tstoeckler’s picture

I think this looks great. Does it make sense to introduce a CacheBackendBase and CacheBackendFactoryBase for this?

Status: Needs review » Needs work
mkalkbrenner’s picture

Does it make sense to introduce a CacheBackendBase and CacheBackendFactoryBase for this

I don't think so. Other Backends don't need that serialization. For example APCu handles serialization by itself (and could be configured in php.ini to use igbinary).

mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new3.36 KB
new16.25 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new3.96 KB
new20.77 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Title: Make data serializer customizable » Make serializer customizable in Cache\MemoryBackend and Cache\DatabaseBackend
Issue summary: View changes
Issue tags: -Needs issue summary update
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new6.25 KB
new27.82 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new2.77 KB
new29.36 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new1.66 KB
new31.27 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new1.75 KB
new31.61 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new1.05 KB
new32.8 KB
mkalkbrenner’s picture

nitpicks

hchonov’s picture

Status: Needs review » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Cache/BackendChainTest.php
@@ -17,9 +17,9 @@ protected function createCacheBackend($bin) {
+      ->appendBackend(new MemoryBackend(\Drupal::service('serialization.phpserialize')))
+      ->prependBackend(new MemoryBackend(\Drupal::service('serialization.phpserialize')))
+      ->appendBackend(new MemoryBackend(\Drupal::service('serialization.phpserialize')));

+++ b/core/tests/Drupal/KernelTests/Core/Cache/ChainedFastBackendTest.php
@@ -20,7 +20,7 @@ class ChainedFastBackendTest extends GenericCacheBackendUnitTestBase {
+    $consistent_backend = new DatabaseBackend(\Drupal::service('serialization.phpserialize'), \Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);

+++ b/core/tests/Drupal/KernelTests/Core/Cache/MemoryBackendTest.php
@@ -18,7 +18,7 @@ class MemoryBackendTest extends GenericCacheBackendUnitTestBase {
+    $backend = new MemoryBackend(\Drupal::service('serialization.phpserialize'));

Kernel tests have access to the container so instead retrieving the php serializer through \Drupal:service you should use $this->container->get.

Beside that great job!

mkalkbrenner’s picture

Status: Needs work » Needs review

@hchonov: your comment is correct. But all the code nearby in the tests uses \Drupal::service(), for example:

  protected function createCacheBackend($bin) {
    $consistent_backend = new DatabaseBackend(\Drupal::service('serialization.phpserialize'), \Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);
    $fast_backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'));
    $backend = new ChainedFastBackend($consistent_backend, $fast_backend, $bin);
    // Explicitly register the cache bin as it can not work through the
    // cache bin list in the container.
    \Drupal::service('cache_tags.invalidator')->addInvalidator($backend);
    return $backend;
  }

For me it looks inconsistent to use $this->container-get() just for the serializaation service there. Maybe all of these service() calls have to be replaced, but that seems to be out of scope for this issue.

hchonov’s picture

+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -200,7 +224,9 @@ protected function getRequestTime() {
+    return array_filter($this->traitSleep(), function($var) {
+      return '_serviceIds' == $var;
+    });

This could be done without array_filter :
$this->traitSleep();
return ['_serviceIds'];

Also we need a comment here why simply returning $this->traitSleep(); is not sufficient.

mkalkbrenner’s picture

This could be done without array_filter :
$this->traitSleep();
return ['_serviceIds'];

That's not true. This code always returns _serviceIds even if $this->traitSleep() didn't add that property!

hchonov’s picture

But it will add it always.. and thinking about it is correct for the method to add the property always as otherwise you do not have to use the trait. Take a look at DependencySerializationTrait::__wakeup it does not check if the property is set but accesses it directly.

mkalkbrenner’s picture

I reviewed the code. You're right the property _serviceIds is always set.

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new32.61 KB

re-roll against 8.3.x

Status: Needs review » Needs work
mkalkbrenner’s picture

That's funny. I had to fix all new usages of the MemoryBackend in the tests. But these were erroneous anyway because they use the obsolete parameter 'bin' which was removed in 8.3.x.

hchonov’s picture

I think the comment in the overridden sleep method should be something like this :

In case the serializer has been injected as a service then we have to ensure it will be properly recovered on wake up, otherwise we do not take care of it in order to prevent data stored in memory backends from being serialized.

What do you think?

mkalkbrenner’s picture

I randomly picked the key "locale.translation_status" from the key_value table from an existing installation. The size of the php serialized string is 27k the igbinary serialized is 7k :-)
I'll go on to get some more numbers and update the issue description.

mkalkbrenner’s picture

new in 8.3.x setiings:

/**
 * Disable caching for migrations.
 *
 * Uncomment the code below to only store migrations in memory and not in the
 * database. This makes it easier to develop custom migrations.
 */
# $settings['cache']['bins']['discovery_migration'] = 'cache.backend.memory';

For sure this feature will benefit from using igbinary if this core patch is committed because of the much smaller memory footprint.

mkalkbrenner’s picture

Issue summary: View changes
mkalkbrenner’s picture

After a discussion with @catch in IRC I came up with the idea to define an interface that ensures that only serializers that are able to handle PHP objects could be injected.

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review

OK, the tests pass, except the ones that currently broken on the 8.3.x regardless of this patch here.

twistor’s picture

Seems like this patch could be simplified greatly if PhpSerialize was set as a default argument. At least for the MemoryBackend.

It's also a BC break, but not sure how those are counted.

mkalkbrenner’s picture

Issue summary: View changes

Seems like this patch could be simplified greatly if PhpSerialize was set as a default argument. At least for the MemoryBackend.

Do you have an idea how to do this?

mkalkbrenner’s picture

twistor’s picture

+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -14,12 +17,33 @@
+  public function __construct(ObjectSerializationInterface $serializer = NULL) {
+    $this->serializer = $serializer ?: new PhpSerialize();
+  }
mkalkbrenner’s picture

@twistor: Sure, that works. But my quick comment wasn't precise enough, sorry :-(

I agree that this will reduce the size of the patch. But that only affects test code.

But such a constructor will open the door for bad usages of the MemoryBackend if it could be instantiated without thinking about the serializer.
Especially for the MemoryBackend I want to inject a compressing serializer.

And the serializer service is a singleton. There's no need to create multiple instances of it - beside in test code.
So the correct default would be to get the serialization.phpserialize service. But this will not work in the test code when the service is not available.

Conclusion:
- Having this default will not simplify the code base, just the test code.
- Having this default allows developers to accidentally bypass the configured serializer.

What we can do is providing a derived TestMemoryBackend within the test code.

mkalkbrenner’s picture

I adjusted the patch according to a discussion with @catch in IRC.

catch: I think for database it makes sense - if we add a new interface to identify serializers that can handle php objects. For memory I'd just do a new cache backend that uses igbinary rather than add the dependency there.
mkalkbrenner: are you fine with the interface name?
catch: hmm, it suggests it's only for serializing objects, but I don't immediately have a better suggestion.
mkalkbrenner: Something like ObjectAware?
catch: yeah that's better :)
catch: and we should open a follow-up postponed to use that for k/v

I renamed the interface to ObjectAwareSerializationInterfacea and reverted the changes to the MemoryBackend.
A new MemoryBackend will then be provided by the igbinary module.

mkalkbrenner’s picture

Issue summary: View changes
mkalkbrenner’s picture

Title: Make serializer customizable in Cache\MemoryBackend and Cache\DatabaseBackend » Make serializer customizable Cache\DatabaseBackend
mkalkbrenner’s picture

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review

Just the annoying standard 8.3 CI fails. The patch itself passes as the retest proves

berdir’s picture

  1. +++ b/core/lib/Drupal/Component/Serialization/ObjectAwareSerializationInterface.php
    @@ -0,0 +1,9 @@
    +/**
    + * Ensures that a serializer is usable for serializing PHP objects.
    + */
    +interface ObjectAwareSerializationInterface extends SerializationInterface {
    

    Coming from #2143149: PHPRedis and igbinary support for read performance and memory reductions..

    what about defining a new service that's specifically for this purpose? Something like serialization.object_serializer or some other generic service name. Then your igbinary module could just override that service and anything that uses it will automatically benefit from it and it won't need specific redis and $other_module integration?

    Finding a good name for that might be a challenge.

  2. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
    @@ -46,11 +55,12 @@ class DatabaseBackend implements CacheBackendInterface {
        * @param string $bin
        *   The cache bin for which the object is created.
        */
    -  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin) {
    +  public function __construct(ObjectAwareSerializationInterface $serializer, Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin) {
         // All cache tables should be prefixed with 'cache_'.
         $bin = 'cache_' . $bin;
    

    I could imagine this is a class that has some custom subclasses in contrib and changing the constructor could break them.

    what we did recently is to add the new argument last and fall back to \Drupal::service() if not provided.

mkalkbrenner’s picture

what about defining a new service that's specifically for this purpose?

That sounds like a simple solution but I don't think that it would be a good solution. With the igbinary module installed you have 4 object aware serializers:

  • PHP
  • PHP compressed
  • igbinary
  • igbinary compressed

For redis it is very important to select a compressing serializer. For the default database cache backend and the key value stores you might want to choose compression as well. But I think you'll sooner or later face a situation where you don't want to have compression for a particular sub-system.
Or you use igbinary and compression for redis but you have another component that somehow shares serialized objects with a different system or exports serialized objects. In this case you should use the default PHP serializer without compression for the maximum compatibility.

I could imagine this is a class that has some custom subclasses in contrib and changing the constructor could break them.
what we did recently is to add the new argument last and fall back to \Drupal::service() if not provided.

I thought about that as well. I did it the current way to follow the given pattern of the key avlue store implementation that already exists in core. But if the maintainers prefer this solution I'm fine to change it.

berdir’s picture

Or you use igbinary and compression for redis but you have another component that somehow shares serialized objects with a different system or exports serialized objects. In this case you should use the default PHP serializer without compression for the maximum compatibility.

I think we might be able to "solve" that with a service name that explains what it is. serializer.optimized_internal sounds weird, but something in that direction.

I assume the developer that defines a service knows whether he can use that or needs to use phpserialize. And if we have a name that explains thoes developers when to use it and when not, then I don't see a problem with your use case?

mkalkbrenner’s picture

I think we might be able to "solve" that with a service name that explains what it is. serializer.optimized_internal sounds weird, but something in that direction.

But if you introduce that service at least the key value store and the database cache backend will use it in core. And redis in contrib :-)
In this case - just like you proposed - it would be easy for the igbinary module to swap that service and to enable the "igbinary compressed" serializer for all of them.
But if you use mongodb with it's internal compression for the key value store and redis for the cache you need to different flavors of that service.
I know that these are edge cases ;-)
Finally that additionally service won't hurt and if others agree, I'm fine to introduce it.

mkalkbrenner’s picture

I prepared a version of the patch that reflects @berdir's suggestions.

Status: Needs review » Needs work
mkalkbrenner’s picture

mkalkbrenner’s picture

Title: Make serializer customizable Cache\DatabaseBackend » Make serializer customizable for Cache\DatabaseBackend
berdir’s picture

Status: Needs review » Needs work
+++ a/core/tests/Drupal/KernelTests/Core/Cache/ChainedFastBackendTest.php
@@ -20,7 +20,7 @@
    */
   protected function createCacheBackend($bin) {
+    $consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);
-    $consistent_backend = new DatabaseBackend(\Drupal::service('serialization.phpserialize'), \Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);
     $fast_backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'));

+++ a/core/tests/Drupal/KernelTests/Core/Cache/DatabaseBackendTest.php
@@ -25,7 +25,7 @@
   protected function createCacheBackend($bin) {
+    return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin);
-    return new DatabaseBackend($this->container->get('serialization.phpserialize'), $this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin);
   }
 

+++ a/core/tests/Drupal/KernelTests/Core/Command/DbDumpTest.php
@@ -69,7 +69,6 @@
     $container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
-      ->addArgument(new Reference('serialization.phpserialize'))
       ->addArgument(new Reference('database'))
       ->addArgument(new Reference('cache_tags.invalidator.checksum'));

+++ a/core/tests/Drupal/KernelTests/Core/Config/Storage/CachedStorageTest.php
@@ -87,7 +87,6 @@
-      ->addArgument(new Reference('serialization.phpserialize'))
       ->addArgument(new Reference('database'))
       ->addArgument(new Reference('cache_tags.invalidator.checksum'));

As commented in IRC, lets keep the explicit argument here, at the new position. The fallback is BC, and we don't want to rely on our own BC, so it will be easy to remove in 9.x

mkalkbrenner’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new2.88 KB
new10.46 KB

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
mkalkbrenner’s picture

Status: Needs work » Needs review

Come on CI ...

wim leers’s picture

How was I now aware of this issue all this time?! :O

For example igbinary shrinks the size of larger serialized PHP objects to one third without losing any performance.

Awesome, how have I never heard of igbinary?!


  1. +++ b/core/core.services.yml
    @@ -421,6 +421,8 @@ services:
    +  serialization.objectaware.default:
    +    alias: serialization.phpserialize
    

    Let's add a comment to this to explain the purpose of this alias.

  2. +++ b/core/lib/Drupal/Component/Serialization/ObjectAwareSerializationInterface.php
    @@ -0,0 +1,9 @@
    +interface ObjectAwareSerializationInterface extends SerializationInterface {
    

    This name sounds a bit strange to me. What's "object-aware" about this? It seems like it's just a serializer capable of handling any PHP data type, there's nothing object-specific about it?

    Also, what does this add on top of \Drupal\Component\Serialization\SerializationInterface?

    The comment does not make this clear at all for me.

  3. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
    @@ -21,6 +22,12 @@ class DatabaseBackend implements CacheBackendInterface {
    +   * The serialization class to use.
    ...
    +   * @var \Drupal\Component\Serialization\ObjectAwareSerializationInterface
    ...
    +  protected $serializer;
    

    "serialization class" vs "serialization interface" vs "serializer"

    Let's please be consistent.

  4. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
    @@ -45,14 +52,17 @@ class DatabaseBackend implements CacheBackendInterface {
    +  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin, ObjectAwareSerializationInterface $serializer = NULL) {
    ...
    +    $this->serializer = $serializer ?: \Drupal::service('serialization.objectaware.default');
    
    +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
    @@ -27,10 +35,13 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
    -  function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider) {
    +  function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, ObjectAwareSerializationInterface $serializer = NULL) {
    ...
    +    $this->serializer = $serializer ?: \Drupal::service('serialization.objectaware.default');
    

    Why make this optional? For BC? https://www.drupal.org/core/d8-bc-policy says constructors do not need to maintain BC.

berdir’s picture

4. We technically don't, but this is becoming a standard pattern, specifically in classes that are likely to be overriden by contrib. I know there is at least one customized cache backend in contrib that implements a max ttl, which likely overrides this. It might or might not have additional constructor arguments, not sure.

mkalkbrenner’s picture

@Wim Leers:

2. @catch and myself agreed on the requirement for such an interface and that Interface name. Have a look at #71. JSON and YAML are suitable for other PHP types except objects. @catch also requested a follow-up to leverage the new interface for the key value store. See #2839862: Ensure that serializers injectable into Drupal\Core\KeyValueStore are aware of PHP objects

3. This inconsistency already exists in core. Have a look at the key value stores which are the blue print for the patch here. If we decide to clean that up, it should be a larger follow-up.

I agree on 1 but there should be a decision on 4 before a final patch.

wim leers’s picture

#94: Yep, for a cache back end, that's fair.

#95.2: that sounds like a great reason… but can you then just add that reasoning to the interface itself as well? Then this would've been instantly clear :)

#95.3: Ok, but then let's at least be locally consistent.

mkalkbrenner’s picture

As discussed with @berdir in IRC there's no need for an object aware serialization default service in core and for example the redis module. Each component should simply use the serialization.phpserialize as it is. That's the defacto default.

I think I now addressed all concerns.

wim leers’s picture

Just one incredibly stupid nit. I'm fine with this now. I'll leave it to @berdir to RTBC.

+++ b/core/lib/Drupal/Component/Serialization/ObjectAwareSerializationInterface.php
@@ -0,0 +1,16 @@
+ * suitable for PHP objects, for example using the PHP string serilization

s/serilization/serialization/

mkalkbrenner’s picture

Fixed the nitpick :-)

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Ok, lets do this. Will have to try out the igbinary module on our sites :)

berdir’s picture

That said, I think this belongs in the cache component.

Also not sure if this needs a change notice or not, e.g. for the new interface. It is a new thing, but is also something that very, very few people will need to worry about I think, so might be more noise than necessary?

berdir’s picture

Component: base system » cache system

Status: Reviewed & tested by the community » Needs work
tstoeckler’s picture

This failed on the new test introduced in #2793849: Handle offcanvas differently at lower widths. The question is: Is that a new random failure or is that related in some super bizarre way? Sending for a re-test anyway...

tstoeckler’s picture

Status: Needs work » Reviewed & tested by the community

Ahh, that was reverted now, so assuming this will come back green then.

Status: Reviewed & tested by the community » Needs work
mkalkbrenner’s picture

Status: Needs work » Reviewed & tested by the community

Retest suceeded.

Status: Reviewed & tested by the community » Needs work
tstoeckler’s picture

Status: Needs work » Reviewed & tested by the community

Bot vs. human: Episode III

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

catch’s picture

Status: Reviewed & tested by the community » Needs review

I'm still not 100% sure about this, for a couple of reasons, didn't really think of the second one during the irc conversation referenced above:

- This adds an additional dependency for the cache subsystem, which in the default case is required entirely to call serialize(). That's loading an interface and a class to call a PHP native function in 99.9% of cases. If we ever do a subtree split, that'll be even more obvious.

- I'm not sure how many classes we have to load to serve a cached page with the database backend, but as above this adds at least one interface and one class to that number. On a site not using the APCu class loader (and using the database cache, so not that unlikely) this might even be measurable.

Seems like we could refactor the serialization logic in the database cache backend to make it easier for the igbinary contrib module to extend from as an alternative.

mkalkbrenner’s picture

Seems like we could refactor the serialization logic in the database cache backend to make it easier for the igbinary contrib module to extend from as an alternative.

We use Redis for most of the caches.

The igbinary module simply swaps the serialization.phpserialize service to do the job for the database and the redis backend at once. The same would happen for any other backend that uses the serialization sevice.

This adds an additional dependency for the cache subsystem, which in the default case is required entirely to call serialize()

From my point of view this default isn't a good choice at all. For a lot of use cases it makes a lot of sense to at least compress the serialized data. That hard-coded call to serialize() prevents us from optimizing the caching.

hchonov’s picture

catch’s picture

From my point of view this default isn't a good choice at all. For a lot of use cases it makes a lot of sense to at least compress the serialized data. That hard-coded call to serialize() prevents us from optimizing the caching.

It doesn't prevent it though. We could refactor the database cache backend so the serialize() call is in a method, then igbinary module could subclass and change that one method. Even as it is now it'd be possible to subclass, just not very efficient due to amount of duplicated code necessary.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kfritsche’s picture

Simple re-roll of #113

Status: Needs review » Needs work
kfritsche’s picture

Fixing the failing test.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

borisson_’s picture

This looks very similar to #2886405: Cache backend should use the serializer service., do we close one of them as duplicate?

Andre-B’s picture

Some related work is being done over at #1281408: Add a compressing serializer decorator as well.

wim leers’s picture

fabianx’s picture

This is just an idea, but perhaps to ensure something like #1281408: Add a compressing serializer decorator is possible, the serializer should potentially have control of the 'serialize' data field of the calling code.

So that several chained serializers can store their formats and don't need to create new objects, which need to be serialized again.

mkalkbrenner’s picture

I just want to mention that https://www.drupal.org/project/igbinary is prepared for this patch here since 18 months.

andypost’s picture

I think it's really bad idea to add this extra overhead (function calls + loading service) to every cache operation
PHP has common way to define serialization and I remember a lot of issues when "milti-head" was configured differently for php serializer

Making another wrapper for build-in php stuff makes it hard to understand/learn for other newcomers

If you wanna make serializer configurable - it require to replace all places where serialize() or unserialize() used + all contrib which rely on it

fabianx’s picture

I think it is fine to allow contrib to override this easily, but what about we add an:

$function = isset($this->serializer) ? $this->serializer : 'serialize';

instead of injecting in core.

And yes switching serializer on the fly is always asking for trouble.

mkalkbrenner’s picture

PHP has common way to define serialization and I remember a lot of issues when "milti-head" was configured differently for php serializer

You can swap the serializer for igbinary this way, but I don't think that you can replace the php serializer by a compressing one this way.

And yes switching serializer on the fly is always asking for trouble.

There're multiple serializers with fallback strategies within https://www.drupal.org/project/igbinary
Using them you don't crash your site by swapping the serializer!
I guess, Drupal\igbinary\Component\Serialization\PhpCompressSerialize will be sufficient for most people.

I think it's really bad idea to add this extra overhead (function calls + loading service) to every cache operation

I don't agree. Having compression enabled gave us a performance boost regarding the complete stack (not just Drupal, but redis and DB caches).
As you might have noticed, there already exists such a service in core for a long time! It's simply not used in every place.
As far as I remember one reason for that was, that you want to ensure in some places that nobody injects a serializer that is not suitable for PHP objects. That's why the patch introduced the ObjectAwareSerializationInterface. Just have a look back in the comments.

tstoeckler’s picture

StatusFileSize
new12.03 KB
daffie’s picture

+1 for me. Great idea to make the backend more flexible. I also agree with @andypost that this issue needs profiling.

claudiu.cristea’s picture

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -73,8 +80,10 @@ class DatabaseBackend implements CacheBackendInterface {
+   * @param \Drupal\Component\Serialization\ObjectAwareSerializationInterface $serializer
+   *   The serializer to use.

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -37,13 +45,16 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
+   * @param \Drupal\Component\Serialization\ObjectAwareSerializationInterface $serializer
+   *   The serializer to use.

Probably we should make clear here that this param is optional only for BC reasons. Then we need a @todo and D9 followup to make this param mandatory in D9.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

fabianx’s picture

Category: Feature request » Task
Priority: Normal » Major
Status: Needs review » Reviewed & tested by the community
Issue tags: -needs profiling +Performance, +scalability

I profiled this and the overhead (which is micro optimization) is well worth the win -- as many more sites have igbinary available out of the box and that saves 50% on serialization operations, which is pretty huge.

Therefore and by reviewing this patch:

RTBC

claudiu.cristea’s picture

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -82,6 +94,7 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
+    $this->serializer = $serializer ?: \Drupal::service('serialization.phpserialize');

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -37,13 +45,19 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
+    $this->serializer = $serializer ?: \Drupal::service('serialization.phpserialize');

We should be triggering a deprecated error here so that when we come to make it mandatory in D9 we've been warning people for 2+ years. We'll also need a legacy test for that.

Other than that, this looks great

claudiu.cristea’s picture

Assigned: Unassigned » claudiu.cristea

Adding the deprecation stuff.

claudiu.cristea’s picture

Assigned: claudiu.cristea » Unassigned
Status: Needs work » Needs review
StatusFileSize
new14.27 KB
new5.42 KB

Implemented #135. Removed the reference to follow-up as is not a standard deprecation policy. We rely on error triggering.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC as #135 is addressed.

tstoeckler’s picture

Thanks @claudiu.cristea!! Also wrote a change notice pretty much at the same time in order to help get this issue across the finish line... ...so we now have two. 🙈 Feel free to delete mine, whoever was the powers to do so.

EDIT: Well, technically, we now have three, because I also wrote a change notice for ObjectAwareSerializationInterface but I think that one has merit on its own, so I think we should keep that one.

larowlan’s picture

Adding credit for those who reviewed to shape the patch, profiled, wrote change records

larowlan’s picture

Status: Reviewed & tested by the community » Needs review

there was no answer to #114 here

catch’s picture

Also the issues I raised in #3014514: Make igbinary the default serializer if available, it saves 50% time on unserialize and memory footprint could be solved by having distinct database tables, which lends towards a subclass too.

@Fabianx did you profile page cache hits without igbinary?

berdir’s picture

@catch: I suppose an implementation that *dynamically* picks the better serializer has a much bigger issue with having to deal with it changing on the fly. If you do it based on manual configuration, it's not that crazy to expect to properly clear caches.

But if we want to, we could also make the table name based on the serializer class dynamically, e.g. check if it's not the default and in that case, use a few characters of the hash of the fully qualified service name or so?

Subclassing wouldn't just require a different class but also a different factory class. The advantage of using the serializer service is that the same can be used for different cache backends, redis already supports this as mentioned above.

fabianx’s picture

Status: Needs review » Needs work

#142 I did and the overhead for the new service injection is neglectable (compared to what Symfony base has as overhead already).

For #114:

As that is static configuration you should be matching that across environments. Also as we live in the "age of docker" it is much more likely to have local dev envs match production.

In the worst case an automatic igbinary service could add the format as a one number thing at the start.

For a cache it's not a big problem if it's invalid information as it can just return FALSE.

Though that is the problem, okay as FALSE is still valid for $item->data.

Hmm, so what we would need is that we can return an invalid value from ObjectSerializationInterface or throw an Exception that we can catch?

e.g. like a class ObjectSerializationInvalidValue that could be used to check that the result is valid?

And as we are introducing a new interface it would be indeed good to get that right.

Because the compressor also has the same problem that it might not be able to decompress the data, if e.g. bzip2 extension is not available, etc. and then still needs to return something sane.

For the cache we can rebuild, but what about other uses where we store permanent non-recreatable data in serialized format?

I think if the object serialization interface says that you need to match it OR ensure you can handle decode failures, then that is okay.

I am setting to "Needs work" for potential interface changes.

mkalkbrenner’s picture

We use igbinary serialization in production for two years now using this core patch and a special branch of the drupal igbinary module: https://cgit.drupalcode.org/igbinary?h=serialization.objectaware.default

We use it for every kind of serialization in Drupal, like caches and the key value stores! If you have a closer look at https://cgit.drupalcode.org/igbinary/tree/src/Component/Serialization?h=... you'll see that I implemented a simple Fallback mechanism to deal with "old" entries that have been serialized earlier in a different format. If required, we can move these Serializers into core, too.

In the current mix of patches, some (small) parts are tricky to use igbinary everywhere. Maybe that could be solved in an easier way if we have everything in core. Meanwhile we use these settings to leverage igbinary early ;-)

$class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src');
$class_loader->addPsr4('Drupal\\igbinary\\', 'modules/contrib/igbinary/src');

$settings['bootstrap_container_definition'] = [
  'parameters' => [],
  'services' => [
    'redis.factory' => [
      'class' => 'Drupal\redis\ClientFactory',
    ],
    'cache.backend.redis' => [
      'class' => 'Drupal\redis\Cache\CacheBackendFactory',
      'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'],
    ],
    'cache.container' => [
      'class' => '\Drupal\redis\Cache\PhpRedis',
      'factory' => ['@cache.backend.redis', 'get'],
      'arguments' => ['container'],
    ],
    'cache_tags_provider.container' => [
      'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum',
      'arguments' => ['@redis.factory'],
    ],
    'serialization.phpserialize' => [
      'class' => 'Drupal\igbinary\Component\Serialization\IgbinaryCompressSerialize',
    ],
  ],
];

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

StatusFileSize
new4.18 KB
new14.42 KB

Re-roll and clean-up

batkor’s picture

subscribe

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.78 KB
new14.49 KB

Fixed deprecation

Status: Needs review » Needs work

The last submitted patch, 149: 839444-149.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.35 KB
new14.63 KB

Fix broken tests and paraphrased messages to fit new coder's standards

Status: Needs review » Needs work

The last submitted patch, 151: 839444-151.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.1 KB
new14.74 KB

Fix message for factory

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

gease’s picture

StatusFileSize
new14.74 KB

Simple reroll against 8.9.x.

Status: Needs review » Needs work

The last submitted patch, 155: 839444-155.patch, failed testing. View results

fabianx’s picture

I think once this passes tests again, it can go back to RTBC. This only adds the serializer for the cache, where re-creating values is not an issue.

gease’s picture

StatusFileSize
new15.97 KB
new1.07 KB

Test fixed by updating cache_factory service registration for kernel test.

gease’s picture

Status: Needs work » Needs review
fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

Only thing that might warrant a fallback thingy is that this breaks BC for anyone overriding the bootstrap container as there the PHP serialization service obviously does not exist.

Do maybe hardcoding the class to use is better instead of \Drupal::service() as it was hardcoded before?

Andre-B’s picture

#160 maybe this should be coordinated with the modules which (might) do this: memcache, redis..?

The last submitted patch, 155: 839444-155.patch, failed testing. View results

The last submitted patch, 155: 839444-155.patch, failed testing. View results

The last submitted patch, 155: 839444-155.patch, failed testing. View results

hchonov’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new15.97 KB
new4.46 KB
new18.2 KB
new2.23 KB
new16.77 KB
new1.01 KB

I had to update the deprecation messages as this might not get committed in 8.8.0, therefore I changed the version from 8.8.0 to 8.8.x.

#160 maybe this should be coordinated with the modules which (might) do this: memcache, redis..?

I am not sure whether the modules override the bootstrap container themselves or the site owners in their settings.php files.

Only thing that might warrant a fallback thingy is that this breaks BC for anyone overriding the bootstrap container as there the PHP serialization service obviously does not exist.

Do maybe hardcoding the class to use is better instead of \Drupal::service() as it was hardcoded before?

I would rather add the PHP serialization service to the retrieved bootstrap container definition. We could achieve this either by adding it directly or by merging the default bootstrap container definition into the retrieved one. I would prefer merging the bootstrap container definitions, as this is a more general solution and will allow us further adding new services to the bootstrap container definition without worrying about overridden bootstrap container definitions.

Here I upload 3 patches:

  1. 839444-165.patch - #158 with updated version reference.
  2. 839444-165--bc-bootstrap-service.patch - BC layer for adding the PHP serialization service to the retrieved bootstrap container definition.
  3. 839444-165--merge-bootstrap-definitions.patch - merging the retrieved bootstrap container definition with the default one.
fabianx’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs framework manager review

My feeling is the explicit declaration is better. Leaving decision to framework managers.

Back to RTBC

gnunes’s picture

I've re-rolled the patches for Drupal 9 and 8.9.
The interdiff contains the resolved conflict in DeprecationListenerTrait
It needs review, please

hchonov’s picture

Back to RTBC as those are simply re-rolls without any functional changes. Thank you, @gnunes!

hchonov’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Version: 8.9.x-dev » 9.0.x-dev
Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -73,8 +80,10 @@ class DatabaseBackend implements CacheBackendInterface {
-  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin, $max_rows = NULL) {
+  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, $bin, $max_rows = NULL, ObjectAwareSerializationInterface $serializer = NULL) {

@@ -82,6 +91,11 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
+    if (!$serializer) {
+      @trigger_error('Calling DatabaseBackend::__construct() without the $serializer argument is deprecated in drupal:8.8.x and the $serializer argument will be required in drupal:9.0.0. See https://www.drupal.org/node/3014688', E_USER_DEPRECATED);
+      $serializer = \Drupal::service('serialization.phpserialize');
+    }
+    $this->serializer = $serializer;

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -37,13 +45,20 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
-  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, Settings $settings = NULL) {
+  public function __construct(Connection $connection, CacheTagsChecksumInterface $checksum_provider, Settings $settings = NULL, ObjectAwareSerializationInterface $serializer = NULL) {
...
+    if (!$serializer) {
+      @trigger_error('Calling DatabaseBackendFactory::__construct() without the $serializer argument is deprecated in drupal:8.8.x and the $serializer argument will be required in drupal:9.0.0. See https://www.drupal.org/node/3014688', E_USER_DEPRECATED);
+      $serializer = \Drupal::service('serialization.phpserialize');
+    }
+    $this->serializer = $serializer;

This is a bit tricky. In the Drupal 9 patch we shouldn't have the deprecation... but making the serializer argument not null is not possible because there are nullable arguments before them. In order to make it required we're going to need to swap arguments around which is possible by removing argument types and doing deprecations but it is not simple.

This needs thinking about.

Also the whole bc-bootstrap-service vs merge-bootstrap-definitions vs doing nothing needs to be chosen before this is RTBC. And if we decide to do merge-bootstrap-definitions then I think we should handle that separately in a blocking issue so we can add explicit test coverage. Putting my framework manager hat on I think ensuring all the services we think should be there are there is important. The bootstrap container is supposed to provide stable place from which to work and this has uncovered the unsurprising that replace-ability means that we need to do more work to make this so.

Also for now I'd target 9.0.x and not worry about 8.9.x and we should handle a backport if and when we get to that.

gnunes’s picture

Status: Needs work » Needs review
StatusFileSize
new15.48 KB
new1.72 KB

I've removed the deprecation warning for 9.0.x
It needs review, please.

Status: Needs review » Needs work

The last submitted patch, 171: 839444-171-9.0.x.patch, failed testing. View results

gnunes’s picture

Status: Needs work » Needs review
StatusFileSize
new13.98 KB
new2.46 KB

I've removed the tests for the deprecating strings.
It needs review, please.

gnunes’s picture

StatusFileSize
new575 bytes
new13.73 KB

Fixed syntax mistake that prevented the test from successfully executing.

andypost’s picture

  1. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
    @@ -82,6 +91,10 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
    +    if (!$serializer) {
    +      $serializer = \Drupal::service('serialization.phpserialize');
    
    +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
    @@ -37,13 +45,19 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
    +    if (!$serializer) {
    +      $serializer = \Drupal::service('serialization.phpserialize');
    

    it needs trigger_error() to point this parameter will be required

  2. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -83,12 +83,21 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    +      'serialization.phpserialize' => [
    +        'class' => 'Drupal\Component\Serialization\PhpSerialize',
    

    it could use PhpSerialize::class syntax

  3. +++ b/core/tests/Drupal/KernelTests/Core/Cache/ChainedFastBackendTest.php
    @@ -20,7 +20,7 @@ class ChainedFastBackendTest extends GenericCacheBackendUnitTestBase {
    -    $consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin, 100);
    +    $consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin, 100, \Drupal::service('serialization.phpserialize'));
    
    +++ b/core/tests/Drupal/KernelTests/Core/Cache/DatabaseBackendTest.php
    @@ -32,7 +32,7 @@ class DatabaseBackendTest extends GenericCacheBackendUnitTestBase {
    -    return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin, static::$maxRows);
    +    return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin, static::$maxRows, $this->container->get('serialization.phpserialize'));
    

    please wrap this long lines

  4. +++ b/core/tests/Drupal/Tests/Core/Cache/DatabaseBackendFactoryTest.php
    @@ -2,12 +2,15 @@
    +use Drupal\Core\DependencyInjection\ContainerBuilder;
    ...
    +use Symfony\Component\DependencyInjection\Definition;
    

    this 2 unused https://www.drupal.org/pift-ci-job/1581642

hchonov’s picture

Re #839444-175: Make serializer customizable for Cache\DatabaseBackend.1:

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -82,6 +91,10 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
+    if (!$serializer) {
+      $serializer = \Drupal::service('serialization.phpserialize');

+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -37,13 +45,19 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
+    if (!$serializer) {
+      $serializer = \Drupal::service('serialization.phpserialize');

it needs trigger_error() to point this parameter will be required

Actually it needs to be required instead of having the fallback - as per @alexpott's comment the deprecation should be removed in D9 - #839444-170: Make serializer customizable for Cache\DatabaseBackend . Therefore we need to remove the fallback and make the parameter required.

andypost’s picture

Status: Needs review » Needs work

@hchonov thank you, misread. Then it needs post update hook to require cache rebuild (container changed)

hchonov’s picture

Actually if we make it required then we will need to re-arrange the constructor arguments, because the previous one is optional. This is not nice, but it should be done. Also the service parameter should be placed before the setting parameters.

However if we make it required, then the cached definition will not have it and therefore it will break while trying to initialize the service. How do we solve this in core? I could think only of leaving it optional in the release where it is introduced, but provide an update for invalidating the container, so that after the rebuild the container will contain the new service definition. Then in a later release we could safely make it required.

xjm’s picture

Version: 9.0.x-dev » 9.1.x-dev
Category: Task » Feature request

This is a minor-only addition. Since 8.9.x is now in beta, I'm moving this to 9.1.x. Thanks!

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

andypost’s picture

Issue tags: +Needs reroll
ravi.shankar’s picture

Issue tags: -Needs reroll
StatusFileSize
new13.74 KB

Added reroll of patch #174.

suresh prabhu parkala’s picture

Status: Needs work » Needs review
StatusFileSize
new13.46 KB
new677 bytes

Tried to fix custom command failures. Please review.

sokru’s picture

StatusFileSize
new519 bytes
new13.5 KB

Resolving cspell notices.

andypost’s picture

Status: Needs review » Needs work

Symfony using term marshaller in context of cache (latest 5.3beta) https://github.com/symfony/symfony/pull/40602/files

Btw needs work to pass pre-checks

kapilv’s picture

Status: Needs work » Needs review
StatusFileSize
new13.5 KB
new561 bytes

Fixed Custom Commands Failed.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

wells’s picture

StatusFileSize
new12.59 KB
new593 bytes

Another attempt to fix cspell fail.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

  1. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
    @@ -82,6 +91,10 @@ public function __construct(Connection $connection, CacheTagsChecksumInterface $
    +    if (!$serializer) {
    +      $serializer = \Drupal::service('serialization.phpserialize');
    

    needs deprecation to be added according to https://www.drupal.org/about/core/policies/core-change-policies/drupal-d...

  2. +++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
    @@ -37,13 +45,19 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
    +    if (!$serializer) {
    +      $serializer = \Drupal::service('serialization.phpserialize');
    

    the same

  3. +++ b/core/lib/Drupal/Core/DrupalKernel.php
    @@ -81,12 +81,21 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    +      'serialization.phpserialize' => [
    +        'class' => 'Drupal\Component\Serialization\PhpSerialize',
    

    could use PhpSerialize::class

andypost’s picture

StatusFileSize
new3.57 KB
new13.33 KB

Fixed #190

daffie’s picture

Status: Needs review » Reviewed & tested by the community

All the code changes look good.
The IS and the CR's are in order.
The patch allows the igbinary module to override the default implementation.
For me it is RTBC.

quietone’s picture

Version: 9.4.x-dev » 10.0.x-dev
quietone’s picture

StatusFileSize
new13.33 KB

Re-uploading patch so test run with 10.0x

catch’s picture

Status: Reviewed & tested by the community » Needs work

#839444-170: Make serializer customizable for Cache\DatabaseBackend is still unresolved - the argument order needs to be swapped, so that the parameter can be required in a later release.

I'm also still not convinced (see #839444-111: Make serializer customizable for Cache\DatabaseBackend from 2017) about adding a dependency on the Serialization component in the cache system, since the serialization component has a dependency on Symfony YAML.

If we wanted to move Drupal\Cache to a component, would we really want symfony/yaml as an implicit dependency? This could be solved by putting the interface somewhere else that's not that component. Symfony itself has had this problem, which is why it introduced symfony/contracts.

mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new11.86 KB

After a long time just living with the patch I really want to see that committed.
Using other serializers is such a performance boost.

I suggest to simply remove the deprection message entirely and to silently fallback to the default serializer if no other one is set. That is perfectly backward compatible and doesn't block anything new.

mkalkbrenner’s picture

StatusFileSize
new11.6 KB

Sorry, I missed the second occurrence.

mkalkbrenner’s picture

StatusFileSize
new13.33 KB
mkalkbrenner’s picture

The patches don't apply to D10 anymore.
I can port the patch again, but it would be great to have feedback on the version in #198 first and if this would be accepted.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new159 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

catch’s picture

I'm also still not convinced (see #839444-111: Make serializer customizable for Cache\DatabaseBackend from 2017) about adding a dependency on the Serialization component in the cache system, since the serialization component has a dependency on Symfony YAML.

This is still the case, but I had another look and I don't think it should hold back this patch. It makes sense to use the serialization component here. If we don't want the dependency on Symfony YAML, we should consider splitting the YAML serialization into a separate SerializationYamlComponent, or making the YAML dependency suggested instead of required - but that wouldn't change anything here.

So to me, #198 looks good.

mkalkbrenner’s picture

Version: 10.0.x-dev » 10.1.x-dev
Status: Needs work » Needs review
StatusFileSize
new12.59 KB
mkalkbrenner’s picture

StatusFileSize
new12.59 KB

Status: Needs review » Needs work

The last submitted patch, 203: 839444_10.0.x.patch, failed testing. View results

mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new13.32 KB

Status: Needs review » Needs work

The last submitted patch, 205: 839444_10.x.patch, failed testing. View results

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mkalkbrenner’s picture

StatusFileSize
new12.34 KB

Updated patch for Drupal 10.1.5

mkalkbrenner’s picture

StatusFileSize
new13.31 KB
mkalkbrenner’s picture

"No space left on device"

Drupal CI is down.

voleger made their first commit to this issue’s fork.

voleger’s picture

Yes, we have GitlabCI now. Rerolled #209 in the MR.

andypost’s picture

one test fails Drupal\KernelTests\Core\DependencyInjection\AutowireTest

voleger’s picture

I left a couple of comments.

vakulrai made their first commit to this issue’s fork.

vakulrai’s picture

Status: Needs work » Needs review
mkalkbrenner’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for fixing the tests!

@catch already agreed on the patch in #201 and we use it for years on multiple production sites. So, I "carefully" set it to RTBC.

kristiaanvandeneynde’s picture

Status: Reviewed & tested by the community » Needs work

Not going to weigh in on whether this can be approved as @catch has already done so, but setting back to NW for a small nitpick. Feel free to RTBC again once that is fixed.

andypost’s picture

Status: Needs work » Needs review

fixed version string and converted properties to constructor promotion

kristiaanvandeneynde’s picture

Status: Needs review » Reviewed & tested by the community

From a code perspective this looks good. Conceptually, I haven't been involved in this discussion at all so I'm still rolling with the approval given in #201

voleger’s picture

Status: Reviewed & tested by the community » Needs work

There is still a problem with argument ordering. The required method argument is placed after the optional. This is against the coding standard because this leads to optional argument becoming required.

andypost’s picture

Status: Needs work » Needs review

@voleger which argument? All added are optional, and last commit fixed it

kristiaanvandeneynde’s picture

I don't see it either, to me it shows as the last argument and is marked as optional. If #222 was a mistake than feel free to set back to RTBC

voleger’s picture

Status: Needs review » Needs work

The deprecation message says that $serializer becomes a required field in drupal:11.0.0. The problem is that the previous argument $max_rows has to remain optional in drupal:11.0.0. We need to keep $max_rows optional.
See https://git.drupalcode.org/project/drupal/-/merge_requests/6296/diffs#51...

The same thing is related to another constructor.
See https://git.drupalcode.org/project/drupal/-/merge_requests/6296/diffs#51...
$settings have to be optional in drupal:11.0.0.

More about required arguments after optional https://php.watch/versions/8.0/deprecate-required-param-after-optional

andypost’s picture

Thank you! Good point, it requires to shif argument somehow

andypost’s picture

Status: Needs work » Needs review

Both arguments added in #2526150: Database cache bins allow unlimited growth: cache DB tables of gigabytes!
So very probably it was just happened before out deprecation policy formed (core 8.4) https://www.drupal.org/node/2891281

So I reordered $max_rows and deprecated to create without settings https://git.drupalcode.org/project/drupal/-/merge_requests/6296/diffs?co...

voleger’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, the changes are reasonable. Good point on pre-deprecation policy changes - agree that settings need to be required.
+1 for RTBC

  • catch committed 577b6900 on 11.x
    Issue #839444 by mkalkbrenner, andypost, gnunes, hchonov, voleger,...
catch’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This causes warnings when doing a site-install using Drush...

PHP Fatal error:  Uncaught Error: Call to a member function get() on null in /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php:1410
Stack trace:
#0 /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php(688): Drupal\Core\DrupalKernel->getHttpKernel()
#1 /Volumes/dev/sites/drupal8alt.dev/vendor/drush/drush/src/Boot/DrupalBoot8.php(326): Drupal\Core\DrupalKernel->terminate(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Render\HtmlResponse))
#2 [internal function]: Drush\Boot\DrupalBoot8->terminate()
#3 {main}
  thrown in /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php on line 1410

Fatal error: Uncaught Error: Call to a member function get() on null in /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php:1410
Stack trace:
#0 /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php(688): Drupal\Core\DrupalKernel->getHttpKernel()
#1 /Volumes/dev/sites/drupal8alt.dev/vendor/drush/drush/src/Boot/DrupalBoot8.php(326): Drupal\Core\DrupalKernel->terminate(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Render\HtmlResponse))
#2 [internal function]: Drush\Boot\DrupalBoot8->terminate()
#3 {main}
  thrown in /Volumes/dev/sites/drupal8alt.dev/core/lib/Drupal/Core/DrupalKernel.php on line 1410

It's because Drush has a DrupalKernel without a container so we should check for that too.

Opened #3419230: Drush error on site-install to fix this.

acbramley’s picture

This issue conflicts heavily with #3113971: Replace REQUEST_TIME in services - one thing we did there was handle string typed $max_rows in DatabaseBackend which this issue didn't handle. That could lead to a BC break.

See https://git.drupalcode.org/project/drupal/-/merge_requests/4302#note_259560

catch’s picture

Priority: Major » Critical
Status: Fixed » Active

Let's either open a quick follow-up for string-typed max rows or roll this one back. Just re-opening for now.

One other review point from #3113971: Replace REQUEST_TIME in services that's also relevant here is we should add the serialization component classes that are loaded on a regular bootstrap (or especially page cache hit) to the core/composer.json classmap so they're optimized in the autoloader.

acbramley’s picture

catch’s picture

acbramley’s picture

andypost’s picture

Priority: Critical » Major
Status: Active » Fixed

Follow-ups are filed, btw $max_rows could be fixed in #3113971: Replace REQUEST_TIME in services

acbramley’s picture

CRs for this issue are also still in draft (maybe that's right?) but do need version updates.

It also may be wise to combine the CRs around the new dependencies once 3113971 is in?

quietone’s picture

Thanks to @acbramley who confirmed the three change records here are correct.

They are now published with correct dates.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.