Skip to content

Performance inefficiency of calling controller_action_predispatch events twice on pages with forward  #36786

Open
@braders

Description

@braders

Preconditions and environment

Steps to reproduce

  1. Install https://github.com/Smile-SA/magento2-module-debug-toolbar to allow the issue to be observed. Alternatively the issue can be observed with use of a step debugger, or by adding some debug logging within Magento\Framework\App\FrontController->dispatchPreDispatchEvents().
  2. Go to a page which has a "forward" action. In other words, any page where an admin-defined URL is mapped to a route. For example, a product, category or CMS page.

Expected result

The controller_action_predispatch event should be fired once.

(plus one each of the dynamic events controller_action_predispatch_* events)

Actual result

The controller_action_predispatch event is fired twice - once for the Forward action, and one for the resulting page (i.e. the product, category etc). You can view this in the observers tab of the debug toolbar extension (if you are using it)

For our site the controller_action_predispatch event is one of the most expensive events, and so the fact it is called twice is having a noticeable performance impact. For example, it means expensive observers like Magento\Persistent\Observer\SynchronizePersistentInfoObserver are unnecessarily running twice.

Additional information

We can't see any reason why you would want controller_action_predispatch to run more than once, especially for a forward action.

A quick-and-dirty solution would be to replace this line:

$this->dispatchPreDispatchEvents($actionInstance, $request);

with:

if (!is_a($actionInstance, '\Magento\Framework\App\Action\Forward')) {
    $this->dispatchPreDispatchEvents($actionInstance, $request);
}

I have tested this on my installation, and cannot see any negative side-effects.

A potentially better solution would be to allow actions to mark themselves as not requiring dispatchPreDispatchEvents to be sent.

A final solution would be to add handling within the observers themselves, to ensure each observer is only ran once per request. I don't like this approach, as it would put an expectation on extension authors to update their extensions in the same way.

Release note

No response

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions