Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to Maho's autoloaders #40

Merged
merged 64 commits into from
Oct 10, 2024

Conversation

justinbeaty
Copy link
Contributor

It started with me trying to enable cache under System > Cache Management, and it not working. I tracked the problem down to this line, but the problem only occurs if you're running via git clone, as I am doing for development.

$files = array_reverse($files);

The reason is that because of the array_reverse it loads app/etc/local.xml before app/etc/config.xml and that's setting <active>0</active> under the db connection node. I re-wrote those functions in the two Config.php files to not use array_reverse so files are loaded in alphabetical order like before, and I can enable cache now.

To make the code a bit cleaner, I defined two new globals, MAHO_IS_STARTER_KIT which is true if you required mahocommerce/maho with composer, and MAHO_ROOT_SOURCE_DIR which always points to the root of maho's code, either in vendor or where you cloned it.


I was also debugging something else, and on a hunch I tried changing the order of include_paths and the autoloaders. I'm pretty sure I solved OpenMage/magento-lts#3462. You can override Zend classes in any of app/code/core/, app/code/local/, app/code/community/, lib/, and any of those directories in 3rd party modules.

One thing that threw me for a loop though was the behavior of opcache. If you were to override Zend/Log/Formatter/Abstract.php, it wouldn't load because opcache has already cached the file with require_once 'Zend/Log/Formatter/Abstract.php'. There is an opcache setting to disable that, and I put that in for developer mode, but on a production system you may need to restart httpd or php-fpm.


Also I wanted to say how much I appreciate your idea of the whole autoloading system. It's amazing. Makes the whole project cleaner and more robust. I need to be offline for a bit, but take some time to review and ask any questions.

app/Mage.php Outdated Show resolved Hide resolved
Copy link
Contributor

@fballiano fballiano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry @justinbeaty, isn't there a simpler way to solve the problem you had cause this is gonna be very difficult to test

app/code/core/Mage/Core/functions.php Outdated Show resolved Hide resolved
lib/Varien/Autoload.php Outdated Show resolved Hide resolved
app/Mage.php Outdated Show resolved Hide resolved
@fballiano
Copy link
Contributor

fballiano commented Oct 4, 2024 via email

@justinbeaty
Copy link
Contributor Author

Git install is used only by us and it is forbidden to store projects, we shouldnt even consider it as a possibility ans it’s never coveres in the doc and never will 😂

I do agree, but it's not great that things break on a git install, because it makes testing harder since things work differently between the two install types.

sorry @justinbeaty, isn't there a simpler way to solve the problem you had cause this is gonna be very difficult to test

I could drop the Zend override stuff from this PR if it will make it easier to test.

@fballiano
Copy link
Contributor

I could drop the Zend override stuff from this PR if it will make it easier to test.

I think people should use a composer patch if they need to patch zf1, overrides are always risky when there is an upgrade of the base file. I think this whole zf1 override thing is overrated.

@justinbeaty
Copy link
Contributor Author

One other thought just now, it might be possible to drop the varien autoloader all together, but still allow Zend overrides. Then we get the fast Composer autoloader if available, and fallback to the slow PSR-0 type.

Although I do agree it's not great practice to allow overrides.

@justinbeaty
Copy link
Contributor Author

@fballiano Check it out, no more Varien auto loader! There's only one caveat. Before you could do stuff like:

$this->_frontController = new mage_core_controller_varien_front();

Where it was case-insensitive, not you cannot, it must be Mage_Core_Controller_Varien_Front.

But I don't think that's a deal breaker, and it doesn't seem like that's always an issue, I think maybe only the first call to the class must be right.

Still working on the PR.

@fballiano
Copy link
Contributor

@fballiano Check it out, no more Varien auto loader!

wow! very interesting!!

There's only one caveat. Before you could do stuff like:

$this->_frontController = new mage_core_controller_varien_front();

Where it was case-insensitive, not you cannot, it must be Mage_Core_Controller_Varien_Front.

mmm I kinda don't think that's a problem, since everybody uses an IDE (I hope) :-D

@justinbeaty
Copy link
Contributor Author

Also, question:

Do you think it's okay to change the output of mahoGetComposerInstallationData() to something like this?

[
    'mahocommerce/maho' => [
        'type' => 'maho-source',
        'path' => '...',
    ],
    'my/module' => [
        'type' => 'magento-module',
        'path' => '...',
    ],
]

There might be a few keys to add to each module for an optimization idea I have.

@justinbeaty
Copy link
Contributor Author

mmm I kinda don't think that's a problem, since everybody uses an IDE (I hope) :-D

I think I've seen some ancient modules that named something like My_Module_Block_MySuperAwesomeBlock, but didn't match the filesystem. But I can't recall, and it's worth not supporting that.

@fballiano
Copy link
Contributor

Do you think it's okay to change the output of mahoGetComposerInstallationData() to something like this?

[
    'mahocommerce/maho' => [
        'type' => 'maho-source',
        'path' => '...',
    ],
    'my/module' => [
        'type' => 'magento-module',
        'path' => '...',
    ],
]

only difference is the key of the array right? I don't see any problem with that at this stage of the project.

I think I've seen some ancient modules that named something like My_Module_Block_MySuperAwesomeBlock, but didn't match the filesystem. But I can't recall, and it's worth not supporting that.

exactly, it's the kind of code that should die anyway

@justinbeaty
Copy link
Contributor Author

only difference is the key of the array right? I don't see any problem with that at this stage of the project.

Right now you return two arrays:

['mahocommerce/maho', 'my/module']
['path1', 'path2']

And yeah, I don't think anyone has relied on it yet. 😄

@fballiano
Copy link
Contributor

right, change it if you think it's better, no problem

@justinbeaty
Copy link
Contributor Author

justinbeaty commented Oct 5, 2024

It is actually faster to check which dirs exist first in included modules instead of adding all possible options into the path. So I added a check in mahoGetComposerInstallationData().

See this test: https://pastebin.com/z3T7cQ2j, test 1 is the old way, test 2 is new, ignore test 3 for now. While we will not be loading 3,581 classes on a page load, the numbers are still much better.

Test 1 took 0.7837700843811
Test 2 took 0.2346019744873
Test 3 took 1.171895980835

Edit, I logged how many lookups are done on a normal page load. Product pages are about 350, so with 10 modules installed, it's 18ms faster.

app/Mage.php Outdated Show resolved Hide resolved
@fballiano
Copy link
Contributor

HAHAHHA I like the title of your last commit

@justinbeaty
Copy link
Contributor Author

Wait, maybe we should have left the _canUseLocalModules variable and method? In case someone overrides the class?

@fballiano
Copy link
Contributor

let me see

@fballiano
Copy link
Contributor

mmm method and variable are "protected" and somebody should have overridden/extended app/code/core/Mage/Core/Model/Config.php which should be quite unusual, would you want to leave them in a disabled state and deprecate them?

@justinbeaty
Copy link
Contributor Author

justinbeaty commented Oct 10, 2024

mmm method and variable are "protected" and somebody should have overridden/extended app/code/core/Mage/Core/Model/Config.php which should be quite unusual, would you want to leave them in a disabled state and deprecate them?

Not sure. One the other hand, if someone did extend Mage_Core_Model_Config, and for some reasons checked if local modules were disabled, they might be better off knowing that the function is removed by getting an error.

But we could also log an exception if someone calls it....

@justinbeaty
Copy link
Contributor Author

We could also check to see if the user has it enabled, and log an exception there too. But I'm almost in favor of just having it completely removed.

@fballiano
Copy link
Contributor

nah, the thing is that if we log an exception not a lot of people check the exception log... if we throw an exception at that point it's the same as the code breaking so... I'd say let's go if you don't want to think about it for a bit

@fballiano
Copy link
Contributor

let's think about it for a couple of hours and then merge, it's a minor thing anyway I think and again I think in production nobody will want to have all local modules disabled, otherwise remove them altogether at that point

@justinbeaty
Copy link
Contributor Author

Okay, let me get back to testing. I'm pretty sure no more changes unless a problem. Will explain some of previous changes soon.

@justinbeaty
Copy link
Contributor Author

justinbeaty commented Oct 10, 2024

Okay, everything is passing with my test modules. Let me overview some changes. I know you understand most of this anyway, but just for completeness sake.

Building our paths with \MahoAutoload::generatePaths()

This is basically the same code we had to build the include paths that would have been used by Varien_Autoload. One fix/improvement is that instead of:
mod_a/app/code/local, mod_a/app/code/community, mod_a/app/code/core, mod_b/app/code/local, mod_b/app/code/community, mod_b/app/code/core

We do all local, all community, all core, which seems more correct:
mod_a/app/code/local, mod_b/app/code/local, mod_a/app/code/community, mod_b/app/code/community, mod_a/app/code/core, mod_b/app/code/core

Generating PSR-0 prefixes with \MahoAutoload::generatePsr0()

Using the paths from above, we let composer know these paths contain PSR-0 classes. Since Varien_Autoload would have scanned those same paths in the same order and found the same files, there should be no breaking change. However, it does save composer from having to look in every module's path for Mage_ classes if we know there are none there.

Composer use-include-path

Because we have generated all of the PSR-0 prefixes, we have no need to let composer look in the include paths for files. If it wasn't found in our PSR-0 scan, it wouldn't have been found by Composer. We do still use set_include_path() in Mage.php so that modules can include or require files that aren't PSR-0 compatible.

Controller Classmaps

I believe the only type of file in Magento core that doesn't use PSR-0 classes are the controllers (but not Controller which do). So, we also scan those files and add them directly to Composer's classmap definition.

This has two benefits: (1) Varien_Router is faster because we don't have to loop all our paths to find the class. (2) We don't have to put require statements in controller classes that extend other controllers. Composer will find the class you're extending.

Regarding point 2, it doesn't break if you do have require statements in controller files, they're just unnecessary so I removed them. The only place I could see something breaking is if a module includes a controller with a relative path like include './AbstractController.php', and another module overrides the abstract class. Don't know if I explained that well, but it's so niche I wouldn't worry about it, and I'm pretty sure it would have been broken without this PR anyway.

Optimized autoloader

Enable with either composer dump -o, or composer config optimize-autoloader true. A warning message is displayed in the admin panel if set to true and in developer mode. One nice thing is that it will tell you which classes conflict, and which one it will be using:
image

It should definitely speed things up in production, and I see no reason not to use it.

Zend overrides

There are now no caveats in overriding Zend, or any other class in lib. Both myzend/override and zend/override work. You also don't have to explicitly define PSR-0 classes in your composer.json or delete the vendor folder. Just put the file in your module's or starter kit's lib folder and it will work.

Breaking changes

Only two I can think of:

  1. Class names are case sensitive now, i.e. mage_core_model_abstract doesn't work anymore.
  2. The removal of disable_local_modules support.

I think that explains everything. Will take a lunch break now, but feel free to do a final review if needed.

@fballiano fballiano changed the title Autoloader improvements Improvements to Maho's autoloaders Oct 10, 2024
@fballiano fballiano merged commit 1576c67 into MahoCommerce:main Oct 10, 2024
15 checks passed
@justinbeaty
Copy link
Contributor Author

Sweet! 🚀🚀🚀

@fballiano
Copy link
Contributor

@justinbeaty merged!! thank you so much for such amazing work! I'll create a page on the website with the info from your last commit.

I've published the new version to https://demo.mahocommerce.com and check how freaking fast it is (there's not even an FPC module nor redis yet!)!

@justinbeaty
Copy link
Contributor Author

@justinbeaty merged!! thank you so much for such amazing work! I'll create a page on the website with the info from your last commit.

I've published the new version to https://demo.mahocommerce.com and check how freaking fast it is (there's not even an FPC module nor redis yet!)!

My absolute pleasure. When I get around to it I am going to try and spin up my store on Maho locally. I have a totally janky process for building the codebase that tries to work around some of the shortcomings of the openmage composer plugins.

@fballiano
Copy link
Contributor

@justinbeaty
Copy link
Contributor Author

boom https://mahocommerce.com/autoloaders/

Nice! 😃

And good luck again to you for the conference. Looks like you'll be speaking in about 10 hours from now.

@fballiano
Copy link
Contributor

Thank mate, I should definitely go to sleep now ehehehe I'm reviewing the slides right now :-D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants