User tests: Successful: Unsuccessful:
Pull Request for Issue #39077 .
use
statements for the legacy implementation traits and 7.0 can remove the traits.The site works.
The site still works!
Please select:
Documentation link for docs.joomla.org:
No documentation changes for docs.joomla.org needed
Pull Request link for manual.joomla.org:
No documentation changes for manual.joomla.org needed
In the past, initialising the plugin was typically done in its constructor. However, plugin objects are constructed for all published plugins as soon as the plugin group they belong in is imported via \Joomla\CMS\Plugin\PluginHelper::importPlugin
. Even if the plugin's event handlers are not used the initialisation has executed, with an adverse impact to the site's performance.
This PR introduces a new method, doInitialise
. Developers can override it and put their plugin's initialisation code in there. This method is called automatically and exactly once, right before the first event handler of this plugin executes. This makes the plugin's initialisation code execute only when it's truly going to be needed during the request's lifetime. If the plugin's event handlers are not used the initialisation code never runs, therefore mitigating the performance impact.
It is possible that a developer might need to disable this feature completely, e.g. because the initialisation is already executed late in the constructor of services which are accessed through an object implementing the Factory pattern as needed — meaning that the initialisation code runs even later than what the doInitialise
method itself can do. In this case, the plugin can set the allowLateInitialisation
to false
.
I was skeptical as to what the performance impact of late initialisation would be since we are essentially doubling the event handers for each event. To quantify the impact I used Apache Benchmark against the Joomla sample data and the URL index.php/sample-layouts/blog
which calls as many events as you are going to get with the sample data.
The command line used was ab -n 500 -c 5 'https://jdev4.local.web/index.php/sample-layouts/blog'
. The site runs on a local server on my MacBook Pro with an Apple M2 processor, 24GiB or RAM, Apache 2.4.54, MySQL 8.0.30, and PHP 8.1.10 (all installed with HomeBrew on macOS Ventura). PHP has OPcache enabled with a revalidation frequency of 2 seconds.
Results WITHOUT late initialisation:
Time taken for tests: 7.199 seconds
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 3 1.0 3 8
Processing: 55 67 15.1 63 176
Waiting: 54 66 14.9 62 175
Total: 57 70 15.2 66 184
Percentage of the requests served within a certain time (ms)
50% 66
66% 68
75% 69
80% 70
90% 79
95% 93
98% 131
99% 136
100% 184 (longest request)
Results WITH late initialisation:
Time taken for tests: 7.224 seconds
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 4 1.5 4 9
Processing: 53 66 16.0 62 169
Waiting: 52 65 15.8 61 164
Total: 56 70 16.0 66 175
Percentage of the requests served within a certain time (ms)
50% 66
66% 68
75% 69
80% 70
90% 78
95% 97
98% 139
99% 150
100% 175 (longest request)
Conclusion: the performance impact is below what can be reasonable measured. The random performance deviation of the server because of OS load, filesystem access, thermal management, PHP compilation, etc has a far more pronounce impact on the test results than the late initialisation feature.
The PR is written in such a way as to maintain full backwards compatibility with Joomla 4.2 (which is fully b/c to Joomla 4.0 and mostly b/c to Joomla 3.10). If a plugins works on Joomla 4.0–4.2 it will still work with this PR applied.
Here is the intention of this PR with regards to deprecations and b/c management over the next three major versions of Joomla (5, 6, and 7).
Plugins should start using the SubscriberInterface and handle events instead of having callback listeners with a variable number of arguments. The CMSPlugin will stop using the legacy code traits in Joomla 6.0 but the traits will not be removed until Joomla 7.0. This gives a minimum of four and a maximum of six years after Joomla 5.0's release for plugins to be refactored. Note that this is in addition to the five years between the introduction of SubscriberInterface in the Joomla 4 alpha versions and the release of Joomla 5.0.
Plugins should move their initialisation to doInitialise
. The constructor WILL NOT be made final as it still needs to be overridden when the developer wants to push services to the plugin object through the constructor in the service provider. Any initialisation in the constructor beyond assigning services pushed by the service provider is, however, now considered a bad practice and not in line with the philosophy of the Joomla architecture.
Plugins should not expect that the loadLanguage
method will be available by default. Plugins should use the \Joomla\CMS\Plugin\LanguageAwareTrait
to make sure the loadLanguage
method is available. The CMSPlugin class will stop loading this trait automatically in Joomla 6.0. Using this trait until Joomla 6.0 is released WILL NOT cause any adverse affects to plugins. Therefore, plugin developers can start refactoring their code as soon as this PR is merged.
The autoloadLanguage
property is now considered deprecated and will be removed in Joomla 6.0. Plugins need to use the \Joomla\CMS\Plugin\LanguageAwareTrait
and call $this->loadLanguage()
manually in their doInitialise
method instead of setting autoloadLanguage
to true. DO NOT try to load any language files in the constructor.
Status | New | ⇒ | Pending |
Category | ⇒ | Libraries |
@richard67 Yes, you can close #39088 as this PR fully addresses the reported problem (and then some).
@nikosdion Well, since you are the author of the issue, you should have the privilege to close it yourself. It would have saved us time.
@nikosdion Unit tests for the CMS plugin are failing, see https://ci.joomla.org/joomla/joomla-cms/59133/1/11 . Possibly they need some update, too?
Labels |
Added:
PR-4.3-dev
|
Unit tests still failing, see my previous comment.
Category | Libraries | ⇒ | Libraries Unit Tests |
Labels |
Added:
?
|
@richard67 I was asleep last night :) I have fixed the tests today and added more tests for the late initialisation code.
@richard67 I was asleep last night :) I have fixed the tests today and added more tests for the late initialisation code.
@nikosdion Sure, you've deserved to sleep and eat and live of course. I did not want to push, only wanted to be sure it doesn't get lost within all the other review comments. Thanks for fixing the unit tests. It will make the other tests (API and system) run, too.
Update: The unit tests are still failing. All fine now.
Status | Pending | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2022-12-07 12:24:40 |
Closed_By | ⇒ | nikosdion |
Status | Closed | ⇒ | New |
Closed_Date | 2022-12-07 12:24:40 | ⇒ | |
Closed_By | nikosdion | ⇒ |
Status | New | ⇒ | Pending |
I am not going to be contributing to this project anymore. I won't be replying to any questions or making any changes until then. I will close any outstanding PRs and delete their code on December 31st, 2022. Merge whatever you want until then.
I guess plugins still going through the CMSFactory to load their language is not considered a problem, given it's three months with no sign of anyone willing to merge it, so I am closing this PR.
Status | Pending | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2023-03-05 17:23:46 |
Closed_By | ⇒ | nikosdion |
@nikosdion The issue can be closed as we have this PR now? Or is there something remaining so it should be kept open?