Follow-up to #2470679: [meta] Identify necessary performance optimizations for common profiling scenarios

Problem/Motivation

Page Cache is still slower as in Drupal 7.

Identify what takes how much time in the process of bootstrapping Drupal to the page cache.

Remaining tasks

- Profile

User interface changes

None.

API changes

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Fabianx’s picture

Title: Page Cache Performance » [meta] Page Cache Performance

Current findings (detailed report to follow):

- Request_Policy is overall a bad idea - performance wise.

There should never be a case where a request policy cannot prevent an object entering the page cache

=> always cache miss
=> better performance

It also prevents from doing a page cache earlier in the process (e.g. settings.php or preContainer - container loading regardless of method takes 50% of the time a full page cache Drupal 7 response did take)

Proposed resolution: Drop request policies as a concept

- HttpKernel.Basic gets @event_dispatcher, @controller_resolver and @request_stack injected

It is in itself not lazy and especially @event_dispatcher gets a lot of configuration injected itself.

That is all not necessary.

However making that service lazy automatically was somehow not possible? (or not performant?)

The following works however:

Edit: It is lazy, I had wrong information in mind.

  http_kernel.basic:
    class: Drupal\Core\StackMiddleware\HttpBasic
    arguments: ['@service_container']
  http_kernel.basic_real:
    class: Symfony\Component\HttpKernel\HttpKernel
    arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']

plus


/**
 * @file
 * Contains \Drupal\Core\StackMiddleware\HttpBasic.
 */

namespace Drupal\Core\StackMiddleware;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
 * Prepares the environment after page caching ran.
 */
class HttpBasic implements HttpKernelInterface {

  /**
   * The dependency injection container.
   *
   * @var \Symfony\Component\DependencyInjection\ContainerInterface
   */
  protected $container;

  /**
   * Constructs a new KernelPreHandle instance.
   *
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $container
   *   The wrapped HTTP kernel.
   */
  public function __construct(ContainerInterface $container) {
    $this->container = $container;
  }

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
    $http_kernel = $this->container->get('http_kernel.basic_real');

    return $http_kernel->handle($request, $type, $catch);
  }

}

Needs an issue and is an easy win. (for page_cache)

Proposed resolution:

Do not inject parameters into the http.basic kernel.

EDIT: Nnm, it is proxied in the original, so the above is not needed ...

Fabianx’s picture

BASE:

63 microsecs / 11 function calls (to setup XHPROF)

exit(0);

--

Autoloader:

365 microsecs  / 139 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us
exit(0);

--

598 microsecs / 233 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$response = new Response("Hi\n\n"); // ~ 200 us
exit(0);

712 microsecs / 250 function calls (Autoloader + Response sending)

$autoloader = require_once 'autoload.php'; // ~ 300 us

$response = new Response("Hi\n\n"); // ~ 200 us
$response->send(); // ~ 100 us
exit(0);

--

912 microsecs / 351 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals() // ~ 200 us;
$response = new Response("Hi\n\n"); // ~ 200 us
$response->send(); // ~ 100 us
exit(0);

--

1,045 microsecs / 427 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$response = new Response("Hi\n\n"); // ~ 200 us
$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

--

KERNEL comes into play:

1,244 microsecs / 569 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us

$response = new Response("Hi\n\n"); // ~ 200 us
$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

--

KERNEL booting

2,475 microsecs / 1,172 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us
$kernel->boot(); // ~ 1,200 us => OUCH!

$response = new Response("Hi\n\n"); // ~ 200 us
$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

ANALYSIS:

$kernel->boot():
  initializeContainer: 1,070 us
    ??? op (load from PHP storage): 404 us
    storage(): 244 us
    attachSynthetic(): 342 us
      Drupal\Core\DrupalKernel::classLoaderAddMultiplePsr4: 325 us
        [internal]: 112 us
        Symfony\Component\ClassLoader\ApcClassLoader::addPsr4: 213 us // __call is expensive, 150 us, called 51 times
          ... Composer\Autoload\ClassLoader::addPsr4: 57 us, should support addMultiplePSR4 natively, called 51 times

=> Can save around 225 us with optimized class loader.

Unfortunately unserialize() takes around 850 us, so nothing to save there.
Loading a big PHP array will cost 600 - 800 us regardless of used storage.

--

Container GET from Kernel

2,481 microsecs / 1,173 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us
$kernel->boot(); // ~ 1,200 us => OUCH!
$container = $kernel->getContainer(); // ~ 6 us

$response = new Response("Hi\n\n"); // ~ 200 us
$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

--

Loading HTTP Kernel ...

3,706 microsecs / 1,561 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us
$kernel->boot(); // ~ 1,200 us => OUCH!
$container = $kernel->getContainer(); // ~ 6 us
$http_kernel = $container->get('http_kernel'); // ~ 1200 us => Double Ouch! 

$response = new Response("Hi\n\n"); // ~ 200 us
$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

ANALYSIS:

$container->get('http_kernel'): 906 us
  ... ::getPageCacheRequestPolicyService(): 141 us
  ... ::getCache_RenderService(): 736 us
    ... ::getCache_Backend_DatabaseService(): 619 us
      ... Drupal\Core\Database\Database::openConnection(): 527 us
    ... ::getCacheFactoryService(): 56 us
    ... ::getSessionConfigurationService(): 25 us

=> Can save 141 us with removal of request policies.

- DB initialization takes longer due to init() statements, nothing we can do there as we need the DB.

The rest is container overhead.

--

Handling request with constant response in Page Cache::handle()

3,867 microsecs / 1,685 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us
$kernel->boot(); // ~ 1,200 us => OUCH!
$container = $kernel->getContainer(); // ~ 6 us
$http_kernel = $container->get('http_kernel'); // ~ 1200 us => Double Ouch! 

$response = $http_kernel->handle($request); // ~ 400 us, 200 us of that is response object creation.

$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

--

ANALYSIS:

$response = $http_kernel->handle($request):
  ... Drupal\Core\ContentNegotiation::getContentType(): 213 us

=> Save 200 us for not constructing Response in index.php, construct response in PageCache => 213 us Content Neg (to be removed)

--

--

Handling request with constant Response on get() // simulated cache hit

4,437 microsecs / 1,949 function calls

$autoloader = require_once 'autoload.php'; // ~ 300 us

$request = Request::createFromGlobals(); // ~ 200 us
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod'); // ~ 200 us
$kernel->boot(); // ~ 1,200 us => OUCH!
$container = $kernel->getContainer(); // ~ 6 us
$http_kernel = $container->get('http_kernel'); // ~ 1200 us => Double Ouch! 

$response = $http_kernel->handle($request); // ~ 937 us => Oh no!

$response->prepare($request); // ~ 300 us
$response->send(); // ~ 100 us

ANALYSIS:

Drupal\page_cache\StackMiddleware\PageCache::handle(): 730 us
  ... Drupal\page_cache\StackMiddleware\PageCache::lookup(): 526 us
    ... Drupal\Core\Cache\DatabaseBackend::get(): 256 us
    ... Symfony\Component\HttpFoundation\Response::__construct(): 140 us // We already have this since Benchmark #0.
    ... Drupal\page_cache\StackMiddleware\PageCache::getCacheId(): 70 us
      ... Symfony\Component\HttpFoundation\Request::getUri(): 64 us
  ... Drupal\Core\PageCache\ChainRequestPolicy::check(): 200 us
    ... Drupal\Core\PageCache\RequestPolicy\NoSessionOpen::check(): 165 us
      ... Symfony\Component\HttpFoundation\Request::getBasePath(): 122 us
    ... Drupal\toolbar\PageCache\AllowToolbarPath::check(): 14 us

=> Killing request policies and using the simple cookie check for session_name() should work.

=> Both Request and Response objects are pretty "heavy" in their implementation.


-----

OVERALL Analysis:

- Autoloader bootstrap is pretty bad (300 us) == 300 us
- Symfony Stack is in itself having an Overhead of: 200 us (createfromGlobals) + 200 us (new Response()) + 300 us (prepare()) + 100 us (send()) == 800 us

=> 1100 us obvious baseline that Drupal 8 can do _nothing_ about (except patch upstream) => 25% of page cache response time

======

Hidden within:

- Autoloader contributes 200 us to PSR-4 loading via indirection and not providing addMultiplePSR-4 - during boot()
- Request::getUri(), Request::getBasePath() == 64 us + 122 us == ~ 200 us

=> another 400 us

=> 1500 us baseline we can do _nothing_ about => 34%

======

The next thing is unserializing the Kernel and loading it (even the compiled one): 650 us

Regardless of used method this contribues with 650 - 800 us, nothing we can do about it as a BIG container needs time to load.

=> 2150 us we can do not much about when using a page cache middleware (that was the total D7 response time) => 48%

======

Database Init + Fetch:

- Init: 527 us
- Fetch: 256 us

=> 783 us => 18 %

=====

Content Neg: 200 us
Overhead for services: ~ 200 us (get_PageCacheRenderService() - DB init)

======

Overall this makes: 3333 us == 75%

======

Drupal\Core\StreamWrapper\PublicStream::basePath(): 102 us (due to calling conf_path() - which creates a request from globals again. Huh?)

=====

The rest is overhead due to container gets(), number of function calls, object construction and autoloading (~ 900 us).

=> 4333 us / 98%

CLASSES LOADED: 54 classes
dawehner’s picture

Great analysis!

Note: On an ideal project I'd use a proper index.php, which means you can setup your kernel as you want.
In HEAD we do something like:

DrupalKernel(PageCacheMiddleware(HttpKernel))) // this should be an onion.

But ideally you would like to have something like

PageCacheMiddlware(DrupalKernel(HttpKernel())

Just adding a couple of issues which fixes some of the problems ...

Drupal\Core\StreamWrapper\PublicStream::basePath(): 102 us (due to calling conf_path() - which creates a request from globals again. Huh?)

#2384675: Deprecate conf_path()

... Symfony\Component\HttpFoundation\Response::__construct(): 140 us // We already have this since Benchmark #0.

One small bit: https://github.com/symfony/symfony/issues/14906

$response = $http_kernel->handle($request):
... Drupal\Core\ContentNegotiation::getContentType(): 213 us

=> Save 200 us for not constructing Response in index.php, construct response in PageCache => 213 us Content Neg (to be removed)

As noted, this will be removed mostly in #2481453: Implement query parameter based content negotiation as alternative to extensions

Fabianx’s picture

#3: Thanks for opening the issues!

#2384675: Deprecate conf_path() unfortunately won't help, because it still re-creates the request from globals.

IMHO Drupal Kernel should inject the Site Path statically into the PublicStream Wrapper as default value.

dawehner’s picture

#2384675: Deprecate conf_path() unfortunately won't help, because it still re-creates the request from globals.

If I understand your point correctly the problem is that we create the request object multiple times? \Drupal\Core\DrupalKernel::getSitePath
though is certainly just a simple getter, so this cannot happen?

IMHO Drupal Kernel should inject the Site Path statically into the PublicStream Wrapper as default value.

Oh I see ... so why do we access the public stream wrapper before the kernel?

catch’s picture

About 50% of the classes loaded from page cache are from #2497143: Proxy services in the container force interfaces to be loaded - this will help with container/autoloader overhead. Made that a child issue of this one.

In general the idea is to drop request policies but keep response policies? I agree that apart from the session cookie there is not much of a use case for request policies - you almost always want to prevent something entering the cache rather than stopping a cache hit.

Oh I see ... so why do we access the public stream wrapper before the kernel?

Without debugging, isn't this phpstorage loading the container?

znerol’s picture

Request policies are there in order to allow contrib authors and site owners to make requests cachable which by default would not be cached. The only use-case in core is the toolbar.

If you extend request policies you normally add allow-rules, while if you extend response policies you add deny-rules.

catch’s picture

Toolbar is probably going to stop doing that assuming #2217985: Replace the custom menu caching strategy in Toolbar with Core's standard caching. gets done.

I've personally forced certain responses to cache in reverse proxies before for authenticated users, but that's always been done by changing the http headers for the response. I guess it comes down to whether that should also be supported by the internal page cache.

Fabianx’s picture

#6: Correct, that is the container loading from PHPStorage using public://.

#7: But can't you just add a ResponseSubscriber instead to allow caching by overriding e.g. a max-age=0 set on the Response?

Also how does a request policy help if the cache item never makes it into the cache in the first place? I will need to check that ...

catch’s picture

The trick with toolbar is that it allows the toolbar path to be cached for authenticated users in the internal page cache, see https://api.drupal.org/api/drupal/core%21modules%21toolbar%21src%21PageC...

Non-zero max age doesn't let you do that - it's skipping the session check that's important there.

That implementation won't be necessary in core once the toolbar is using the new menu render caching, so it comes down to whether there's a use case for that.

Fabianx’s picture

Hm, so but not having it is not a security issue, right - it would just make things slower - because they only override things that are disallowed?

So if I moved page_cache to a bootstrap service via settings.php and static namespace registration for the page_cache module, I would miss out on request policies, but then the page_cache middleware could still check them.

Double check, but that check itself costs overall only 5 ms (and probably less because it would only need to deal with denied things, so the double hit is worth the 1-2 ms for cache hit.

Wim Leers’s picture

#2: wow, great detective work!

#3:

this should be an onion.

:P

Fabianx’s picture

Giving short update:

- Using our own composer autoloader should save 500 us
- Spoke with znerol, while removing request policies is not a good idea, removing the possibility to return DENY from request policies is.
- If only DENY is allowed, it is no security issue to not take request policies into account, page_cache then just is asked twice.
( Will also need logic to check $_COOKIE for SESS* as that is no longer available pre-container. )

=> Overall: Pre-container page_cache is feasible.

Upstream Symfony is very happy to accept patches for performance improvements - we'll see what will be possible to optimize.

TL;DR: I am positive D7 page cache speed can almost be reached.

Wim Leers’s picture

TL;DR: I am positive D7 page cache speed can almost be reached.

\o/

Fabianx’s picture

Quick update:

- 3.5 ms ( 5.7 ms before) reached with autoloader and some Symfony optimizations.
- 2.2 ms reached with a pre-kernel middleware.

I think around 1.9 ms is D7 on that same machine ...

Wim Leers’s picture

Nice! :)

Fabianx’s picture

Category: Task » Plan

Issues that need to be created based on my latest local patch:

- vendor/symfony/http-foundation/ServerBag.php - check if key starts with 'H' via array string syntax; not sure it will fly upstream, but it saves a lot.
- vendor/symfony/http-foundation/ServerBag.php - Use if (!empty($authorizationHeader)) instead of === null to remove unnecessary stripos() calls
- Ensure Request::createFromGlobals() is only called once per request, used a GLOBAL set by DrupalKernel in my patch, could use the new &DrupalStatic component if available.
- Move accept header negotiation after page_cache (saves 0.2 ms - not yet done locally, so still to gain from above numbers!)
- Instead of populating classmap with files, use files directly (order matters, saves 11 autoloader calls)
- Use getRequestUri() instead of getUri() and figure out domain in a cheaper way than $request->getUri(), remove $request->getFormat().
- Prepare Response already in PageCache ($response->prepare() and save prepared Response to cache instead of whatever it gets, saves loading of CacheableResponse and CacheableResponseInterface, e.g. have very fast PreparedResponse class, which just does the necessary header sending and response sending.
- Consider using some D7 code for things like request_uri() in an utility class, our D7 version uses 3 us, while Symfony needs 77 us for getRequestUri() and I _think_ around 200 us for getUri().

Part of autoloader issue, so don't need issues, but noting as subtasks here:

- Use optimized PSR-4 loading of optimized build autoloader
- Register APC prefix in optimized autoloader

Fabianx’s picture

!!! WARNING !!! - The following code is very very hacky and very work-in-progress - it might not be suitable to minors and could generate feelings of severe hacky-code-paranoia. - !!! WARNING !!!

So after you have been warned (and with the @todo taken into account that this might not be possible, here are the numbers):

With pre-container-kernel "middleware" (hacked into index.php for now):

Not sure all of this is feasible, but pre-container middleware could be very very fast - is what it shows.

Without pre-container kernel middleware:

--

Patch includes all things from above and we need to split into sub-issues.

Fabianx’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 18: meta_page_cache-2501989-18.patch, failed testing.

Fabianx’s picture

+++ b/core/autoloader/ClassLoaderDrupal.php
@@ -0,0 +1,1207 @@
+    private $prefixDirsPsr4 = array (
+  'Zend\\Stdlib\\' => ¶
+  array (
+    0 => '/var/www/html/core/vendor/zendframework/zend-stdlib',
+  ),

Oh, yeah, uhm, absolute paths won't work ...

Need to fix that here, too ...

Well at least the test-run will be really fast ;).

dawehner’s picture

Impressive numbers!

+++ b/core/autoloader/autoload_fast.php
@@ -0,0 +1,31 @@
+require $baseDir . '/lib/Drupal/Component/Utility/Timer.php';

I think we can rid of timer now, given that we removed the timer out of the Drupalkernel

Wim Leers’s picture

Yes, absolutely impressive numbers! Go Fabian :)

Fabianx’s picture

FileSize
90.03 KB

Patch won't apply either, but new patch solves the absolute paths by moving variable initialization to __construct() :).

!!! WARNING !!! - STILL VERY HACKY - !!! WARNING !!!

Fabianx’s picture

New find:

No middleware in core actually implements the TerminableInterface.

Therefore we can remove those services already during container building and not pass them on to Stack.

As we have a container based middleware, I would even vote to remove that feature completely and always pass an empty array ...

Then only the first middleware after a responder like page_cache needs to be proxied, which saves time and CPU.

Edit: By doing so one saves another 250 us and by moving page_cache as first middleware (prio: 600), we save another 300 us.

=>

New low:

Run #55847d311f345 Run #558535fd95e3f Diff Diff%
Number of Function Calls 1,090 921 -169 -15.5%
Incl. Wall Time (microsec) 3,738 3,186 -552 -14.8%
Incl. MemUse (bytes) 1,851,048 1,763,448 -87,600 -4.7%
Incl. PeakMemUse (bytes) 1,881,800 1,789,376 -92,424 -4.9%

=====

Request->getHost() is very slow, should be cached in the Request once trusted proxies are set - Symfony is very problematic there with using statics: It means an earlier getHost() potentially is different from a later one. If someone sets new information on the request, IMHO need to call resetHost() on the request.

There is a really good reason why PSR-7 objects are immutable - I get that now ...

======

There is several file_exists() in MTimeProtectedFastFileStorage (not gonna optimize those) and one is_readable() in Settings::initialize, which probably could be changed to @require_once instead ...

There is one file_exists() in findSitePath().

======

Fabianx’s picture

Spent a little more time to optimize pre-kernel page cache:

Latest achievement:

LEFT: Drupal 7
RIGHT: Drupal 8

=> Comparable performance is _reachable_.

Run #55856ea694669 Run #558569a9a8f54 Diff Diff%
Number of Function Calls 537 385 -152 -28.3%
Incl. Wall Time (microsec) 1,941 1,819 -122 -6.3%
Incl. MemUse (bytes) 480,824 747,016 266,192 55.4%
Incl. PeakMemUse (bytes) 485,880 777,840 291,960 60.1%

=========

It depends on how much upstream patches are accepted and to what lengths we want to go, but it seems possible at least.

( and the above includes cache tags for Drupal 8, but none for Drupal 7 (!))

Latest upstream patches include:

- Add static caches for host, scheme and httpHost.

Latest local optimizations include:

- Use static::CACHE_PERMANENT in DatabaseBackend.php to save class load of 'Cache" class
- Wrap Response in a new Response in PageCache
- Use $request->getSchemeAndHttpHost . $request->getRequestUri() as $cid. (good enough and faster than to normalize)
- Hardcode values for authenticated and anonymous in bootstrap.inc -- saves a class load, those are deprecated anyway and don't think we'll change them in D8 again ...

Probably the Response->prepare() change must be reverted though as the request can change (e.g. HTTP 1.0 vs. HTTP 1.1)

Wim Leers’s picture

WOW!!!!!!!!

catch’s picture

#1055862: Require sites.php to opt-in for multi-site support/functionality was intended to remove all file_exists() from findSitePath() but the actual committed patch didn't. I'd still go for refactoring that so we can fully ditch it.

Also wow++

Fabianx’s picture

Status: Needs work » Needs review
FileSize
99.73 KB

Latest patch and latest benchmark:

Drupal 7 vs. Drupal 8 with pre-container page cache.

Run #55856ea694669 Run #558b522b352ab Diff Diff%
Number of Function Calls 537 518 -19 -3.5%
Incl. Wall Time (microsec) 1,941 1,919 -22 -1.1%
Incl. MemUse (bytes) 480,824 828,008 347,184 72.2%
Incl. PeakMemUse (bytes) 485,880 857,632 371,752 76.5%

Obviously with more complexity (brought Response::prepare back and added the two hardcoded request policies (check for cli and session active) there is more effort, so the GAP is smaller.

But overall this page cache is about as fast / slow as Drupal 7 (but Drupal 8 has the cache tags supported).

And the attached patch might even work ...

Lets see ...

Given the above numbers I recommend we open the major / critical issue to remove the possibility of request policies to deny something, but only return ALLOW. (API change). That is at this point the only thing blocking this patch.

Oh and likely session_name($session_configuration->getName()) should be called, then use session_name() to check for request->cookies->get(session_name()) ourselves.

As ::lookup in page cache relies on session_name() for some decisions.

Status: Needs review » Needs work

The last submitted patch, 29: meta_page_cache-2501989-29.patch, failed testing.

Fabianx’s picture

Status: Needs work » Needs review
FileSize
4.26 KB
100.14 KB

Another try.

Status: Needs review » Needs work

The last submitted patch, 31: meta_page_cache-2501989-31.patch, failed testing.

Fabianx’s picture

Status: Needs work » Needs review
FileSize
4.75 KB
100.82 KB

Okay, two competing autoloaders are not fun. (PHPUnit loaded the composer one early)

Solved it by returning the composer autoloader in case the factory is loaded already.

Also moved file loading to a static factory method, again 3 function calls more, but no overhead lost. (phew)

Could be green (very optimistic), lets see ...

Status: Needs review » Needs work

The last submitted patch, 33: meta_page_cache-2501989-33.patch, failed testing.

Berdir’s picture

Hm.. not being able to deny caching does break a use case I have (I have a special cookie that I'm using that I want to prevent the page cache on certain pages only).

If we remove that, can we at least make sure that we have support to set this through settings.php, which is what I used before request policies were added. So some sort of global or static method that I can call through that?

Fabianx’s picture

Status: Needs work » Needs review
FileSize
688 bytes
100.87 KB

Okay, so _that_ happens when you forget to turn off page_cache for POST requests :p.

Status: Needs review » Needs work

The last submitted patch, 36: meta_page_cache-2501989-35.patch, failed testing.

Fabianx’s picture

Status: Needs work » Needs review
FileSize
104.7 KB
4.73 KB

Fix tests from removal of getRequestFormat().

Status: Needs review » Needs work

The last submitted patch, 38: meta_page_cache-2501989-37.patch, failed testing.

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.

andypost’s picture

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

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

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now 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.

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.

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.

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.

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.

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.

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.

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

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

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.

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.

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.

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

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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.