0

I have a site with a few complicated forms. They require a lot of CPU time to calculate, so I am caching the $form array in order to be able to deliver the form quickly to the user. To do this, I am using an abstract class based on FormBase. Here is the code for this class:

abstract class PM_FormBase extends FormBase {
  public function buildForm(array $form, FormStateInterface $form_state) {
    $formValues = $form_state->getUserInput();
    // If this is not a form submission, so get from cache
    if (0 == count($formValues)) {
      $building = 'Park_Avenue_Manor'; // Hard coded for now, for testing
      $cid = $building . '_' . $this->getFormId();
      if ($cache = \Drupal::cache()->get($cid)) {
        \Drupal::messenger()->addMessage('From Cache'); // Just for Testing
        $form = $cache->data;
      }
      else {
        \Drupal::messenger()->addMessage('NO, NOT From Cache'); // Just for Testing
        $form = $this->buildCompleteForm($form, $form_state);
        // Set cache to expire 1 hour
        \Drupal::cache()->set($cid, $form, strtotime("+1 hours"));
        // Store form ID as well. This is used in function buildFormsCache
        $formIds = \Drupal::cache()->get('PM_FormBase_Form_IDs');
        if (!$formIds) $formIds = (object)['data' => []];
        if(!in_array($cid,$formIds->data)) {
          $formIds->data[] = $cid;
          \Drupal::cache()->set('PM_FormBase_Form_IDs', $formIds->data);
        }
      }
    }
    // If it's a form submission, so process regularly
    else {
      $form = $this->buildCompleteForm($form, $form_state);
    }
    return $form;
  }
}

Then an actual form definition looks like this:

namespace Drupal\midwayliving\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class showBuildingStatus extends PM_FormBase {
  public function getFormId() {
    return 'showBuildingStatus_form';
  }
  public function buildCompleteForm($form, $form_state) {

Based on the addMessage code, I can verify that the caching is working as expected. When I initially implemented this, the load time for the showBuildingStatus form went down from 20 seconds to 2 seconds. The PM_FormBase code was a bit simpler then.

Today if I turn off the caching (disable the PM_FormBase code), the page loads in 30 or 50 seconds. If I enable the caching then it takes 20 or 30 seconds.

This is on our development server, that no one is using except me. On the live server it takes 30 or 35 seconds. To load a simple static page takes a second or two, so the server and the site are working normally.

I don't understand why a static page loads in 2 seconds, but a cached form takes 30 seconds.

7
  • 1
    A static page like just HTML? Is this using memory backed cache or is it stored in the database?
    – Kevin
    Jan 18 at 18:51
  • Yes, just HTML in a Drupal node. Cache is in the DB.
    – Hershel
    Jan 18 at 18:57
  • Even if you cache the form build it still needs to be processed and rendered. But you can cache the rendered form in the render cache the same as any other rendered HTML.
    – 4uk4
    Jan 18 at 19:36
  • 3
    I would suggest a debugger, such as xdebug, or a profiler, such as Web Profiler (drupal.org/project/webprofiler) so you can drill down and figure out exactly what is taking this amount of time. The caching code you have shown looks mostly fine.
    – Jaypan
    Jan 18 at 19:58
  • Try implementing Memcache or Redis to take the strain off the database. Then profile from there.
    – Kevin
    Jan 18 at 20:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.